.app{position:relative;height:100vh;overflow:hidden;display:grid;grid-template-rows:auto minmax(0,1fr);isolation:isolate}

.bg-grid{
  position:absolute;inset:-10%;z-index:0;pointer-events:none;
  background-image:
    repeating-linear-gradient(0deg,rgba(185,143,58,.075) 0 1px,transparent 1px 80px),
    repeating-linear-gradient(90deg,rgba(185,143,58,.075) 0 1px,transparent 1px 80px);
}
.bg-vignette{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse at 50% 48%,var(--glow-gold) 0%,var(--vignette-mid) 42%),
             radial-gradient(ellipse at 50% 50%,var(--vignette-mid) 45%,var(--vignette-edge) 100%);
}
.fx{position:absolute;inset:0;z-index:4;pointer-events:none;width:100%;height:100%}

.topbar{
  position:relative;z-index:3;display:flex;align-items:center;justify-content:space-between;
  gap:2vmin;padding:1.8vmin 3vmin 1.6vmin;border-bottom:1px solid rgba(201,162,69,.2);
  background:var(--topbar-veil);
  transition:opacity .7s var(--ease-out),visibility .7s;
}
.rail{display:flex;flex-direction:column;gap:1vmin;min-height:0;transition:opacity .7s var(--ease-out),visibility .7s}
.stage-frame{
  position:relative;aspect-ratio:1;height:100%;width:auto;
  max-height:var(--ring-size);max-width:100%;
  display:grid;place-items:center;
  transition:opacity .45s var(--ease-out);
}
.brand{
  display:flex;flex-direction:column;align-items:stretch;gap:.42em;
  min-width:0;width:max-content;max-width:100%;
}
.brand-hotel{
  font-family:var(--font-brand);font-size:clamp(16px,2.05vmin,28px);font-weight:600;line-height:1;
  letter-spacing:.14em;text-indent:.14em;text-transform:uppercase;
  white-space:nowrap;text-align:center;
  background:linear-gradient(178deg,var(--gold-100) 0%,var(--gold-200) 46%,var(--gold-400) 100%);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
}
.brand-meta{
  display:flex;align-items:center;justify-content:center;gap:.5em;width:100%;
  font-size:var(--fs-micro);line-height:1;color:var(--gold-400);
  text-transform:uppercase;letter-spacing:.16em;white-space:nowrap;
}
.brand-meta > span:not(.brand-rule):not(.brand-sep){margin-inline-end:-.16em}
.brand-rule{flex:1 1 0;width:auto;min-width:1em;height:1px;background:var(--gold-400);opacity:.55}
.brand-sep{width:3px;height:3px;border-radius:50%;background:var(--gold-400);opacity:.7;flex:none}
.topbar-right{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:1.6vmin;font-size:var(--fs-small);color:var(--text-2)}
.topbar .danger-btn{font-size:inherit;padding:.45em .9em}
.danger-btn{padding:.55em 1.1em;border:1px solid rgba(196,84,63,.5);border-radius:var(--radius);color:#D97D6B;font-size:12px;background:transparent;cursor:pointer}
.danger-btn:hover{background:rgba(196,84,63,.16)}
.danger-btn.is-armed{background:rgba(196,84,63,.24);color:#F0AA99}
.ghost-btn{  padding:.5em 1em;border:1px solid rgba(201,162,69,.35);border-radius:var(--radius);
  color:var(--gold-300);font-size:var(--fs-small);transition:background .18s,border-color .18s,color .18s;
}
.ghost-btn:hover{background:rgba(201,162,69,.12);border-color:var(--gold-300)}
.ghost-btn.is-on{background:var(--gold-300);border-color:var(--gold-300);color:var(--btn-on-fg)}
.ghost-btn:disabled{opacity:.35;cursor:default;pointer-events:none}

.layout{
  position:relative;z-index:2;display:grid;
  /* Rails must stay equal width: the stage column's centre is the axis the
     wheel sits on, and the centred .landmark is on the app's axis. Unequal
     rails push those two apart and the facade reads off-centre. */
  grid-template-columns:minmax(180px,18vw) minmax(0,1fr) minmax(180px,18vw);
  gap:2.5vmin;padding:2vmin 3vmin;min-height:0;
}
.rail-right{min-width:0}
.result-list{
  list-style:none;display:flex;flex-direction:column;gap:.7vmin;
  overflow-y:auto;overflow-x:hidden;padding-right:4px;min-height:0;flex:1;
  scrollbar-width:thin;scrollbar-color:var(--line) transparent;
}
.result{
  display:flex;align-items:center;gap:.5em;
  padding:.62em .8em;border:1px solid var(--line-soft);border-radius:var(--radius);
  background:var(--ink-600);font-size:var(--fs-small);color:var(--text-2);
}
.result .r-body{display:flex;flex-direction:column;gap:.15em;min-width:0;flex:1}
.result .r-name{color:var(--gold-100);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.result .r-prize{color:var(--gold-400);font-size:var(--fs-micro);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.result-redraw{
  flex:none;padding:.2em .45em;border:1px solid rgba(201,162,69,.28);border-radius:4px;
  color:var(--gold-400);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  opacity:.7;cursor:pointer;
}
.result-redraw:hover{opacity:1;border-color:var(--gold-300);color:var(--gold-200);background:rgba(201,162,69,.12)}
.result.is-wait{
  border-style:dashed;border-color:rgba(201,162,69,.55);
  background:rgba(201,162,69,.1);
  min-height:2.7em;justify-content:center;
}
.result.is-wait .r-name{color:var(--gold-300);font-weight:400}
.result.is-wait .r-prize{color:var(--gold-300)}

/* Diamond crest sits on .stage-frame (not .stage-3d) so tunnel push/scale
   during a draw does not enlarge it. */
.stage-frame{
  position:relative;aspect-ratio:1;height:100%;width:auto;
  max-height:var(--ring-size);max-width:100%;
  display:grid;place-items:center;
}
.crest{
  position:absolute;left:50%;bottom:calc(100% + 1.2vmin);
  transform:translateX(-50%);
  width:40%;overflow:visible;fill:none;z-index:3;pointer-events:none;
}
.crest-rule{stroke:var(--gold-400);stroke-opacity:.45;stroke-width:1}
.crest-dot{fill:var(--gold-400);fill-opacity:.6;stroke:none}
.crest-gem{stroke:var(--gold-300);stroke-opacity:.75;stroke-width:1.2}
.crest-gem-in{fill:rgba(232,199,122,.16);stroke:var(--gold-200);stroke-opacity:.5;stroke-width:.8}
.crest-fan{stroke:var(--gold-400);stroke-opacity:.3;stroke-width:1}

/* Centred on the app's vertical axis, behind the wheel (z 1 sits above the
   vignette, below .layout). Runs off the bottom of the viewport so the facade
   rises out of the frame instead of ending on a visible box edge. */
.landmark{
  position:absolute;z-index:1;left:50%;transform:translateX(-50%);
  /* top and bottom offsets stay equal and opposite: the box keeps its 100vh
     height and the pair just slides the facade down the frame. */
  top:24vh;bottom:-24vh;width:min(78vh,62vw);
  pointer-events:none;user-select:none;
  transition:top .95s var(--ease-out),bottom .95s var(--ease-out),width .95s var(--ease-out);
  /* Shared by the art and the sweep so the two fade identically. Horizontal
     radius stays at 50% so alpha reaches zero exactly at the box sides — any
     wider and the sweep draws hard vertical edges. The tall vertical radius
     plus the raised focal point keep a faint tail over the top of the tower,
     so the roofline and crown read instead of cutting off; stacked masks
     would union rather than intersect, so it has to be one gradient. */
  --landmark-mask:radial-gradient(50% 88% at 50% 76%,
    #000 26%,rgba(0,0,0,.6) 58%,rgba(0,0,0,.22) 86%,transparent 100%);
}
.landmark-halo{
  position:absolute;inset:auto 0 0 0;height:70%;
  background:radial-gradient(ellipse at 50% 88%,var(--glow-gold-soft),var(--vignette-mid) 66%);
}
.landmark-art{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 100%;
  mix-blend-mode:screen;opacity:.35;
  /* Crush the JPEG's near-black ground so the screen blend leaves only the gilding. */
  filter:contrast(1.55) brightness(.98) saturate(1.15);
  -webkit-mask-image:var(--landmark-mask);
  mask-image:var(--landmark-mask);
  transition:opacity .95s var(--ease-out),filter .95s var(--ease-out);
}
body.theme-white-gold .landmark-art{
  /* Pearl+gold artwork: multiply drops the white ground, keeps gilding. */
  mix-blend-mode:multiply;opacity:.92;
  filter:contrast(1.12) brightness(1.02) saturate(1.08);
}
body.theme-white-gold .landmark-scan{mix-blend-mode:multiply;opacity:.55}
/* Slow highlight sweeping up the facade, like light raking across gilding.
   Carries the same mask as the art — the band is a full-width gradient, so
   without it the sweep draws hard vertical edges at the box sides. */
.landmark-scan{
  position:absolute;inset:0;mix-blend-mode:screen;opacity:.5;
  background:linear-gradient(180deg,rgba(247,233,192,0) 42%,rgba(247,233,192,.09) 50%,rgba(247,233,192,0) 58%);
  -webkit-mask-image:var(--landmark-mask);
  mask-image:var(--landmark-mask);
}

.rail{display:flex;flex-direction:column;gap:1vmin;min-height:0}
.rail-head{font-size:var(--fs-label);font-weight:500;color:var(--gold-300);letter-spacing:.2em}
.prize-list,.special-list{list-style:none;display:flex;flex-direction:column;gap:.7vmin;overflow-y:auto;overflow-x:hidden;padding-right:4px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.prize,.special{
  display:flex;align-items:center;justify-content:space-between;gap:.6em;
  padding:.62em .8em;border:1px solid var(--line-soft);border-radius:var(--radius);
  background:var(--ink-600);font-size:var(--fs-small);color:var(--text-2);
  transition:border-color .25s,background .25s,color .25s,transform .25s var(--ease-out);
}
.prize .p-name,.special .s-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.prize .p-status,.special .s-status{color:var(--gold-400);font-size:var(--fs-micro);flex:none}
.prize.is-done,.special.is-done{border-color:rgba(201,162,69,.4);color:var(--gold-300)}
.prize.is-done .p-status,.special.is-done .s-status{color:var(--gold-400)}
.prize.is-active,.special.is-active{
  background:var(--ink-active);border-color:var(--gold-200);color:var(--gold-100);
  transform:translateX(.3em);
}
.prize.is-active .p-status,.special.is-active .s-status{color:var(--gold-200)}
.prize,.special{cursor:pointer}
.prize:hover,.special:hover{border-color:rgba(201,162,69,.45)}

.special-list{flex:0 1 auto}
.special-add{display:grid;grid-template-columns:1fr 4.8em;gap:.5vmin;margin-top:.4vmin;flex:none}
.special-add input{
  padding:.55em .7em;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--ink-600);color:var(--text-2);font-size:var(--fs-micro);min-width:0;
  height:2.5em;
}
.special-add input::placeholder{color:var(--text-4)}
.count-field{position:relative;display:block;min-width:0}
.count-field input[type=number]{
  width:100%;padding-right:1.45em;text-align:center;
  -moz-appearance:textfield;appearance:textfield;
}
.count-field input[type=number]::-webkit-outer-spin-button,
.count-field input[type=number]::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0;display:none;
}
.count-step{
  position:absolute;top:0;right:0;bottom:0;width:1.35em;
  display:flex;flex-direction:column;
}
.count-btn{flex:1;position:relative;padding:0;min-width:0;font-size:0;line-height:0;cursor:pointer}
.count-btn::before{
  content:"";position:absolute;left:50%;top:50%;width:.32em;height:.32em;
  border-right:1px solid var(--gold-400);border-bottom:1px solid var(--gold-400);
  opacity:.7;
}
.count-btn[data-dir="1"]::before{transform:translate(-50%,-35%) rotate(-135deg)}
.count-btn[data-dir="-1"]::before{transform:translate(-50%,-65%) rotate(45deg)}
.count-btn:hover::before{opacity:1;border-color:var(--gold-200)}
.dashed-btn{
  grid-column:1/-1;padding:.6em;border:1px dashed rgba(201,162,69,.5);border-radius:var(--radius);
  color:var(--gold-400);font-size:var(--fs-micro);transition:background .18s,color .18s;
}
.dashed-btn:hover{background:rgba(201,162,69,.12);color:var(--gold-200)}
.rail-note{font-size:var(--fs-micro);color:var(--text-4);line-height:1.6;margin-top:auto;padding-top:1vmin}

.stage{position:relative;display:grid;place-items:center;min-height:0;perspective:1400px;perspective-origin:50% 50%}
.stage-3d{
  position:absolute;inset:0;width:100%;height:100%;
  display:grid;place-items:center;transform-style:preserve-3d;
}
.rings{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.rings .ring{fill:none;transform-box:fill-box;transform-origin:center}
.ring-ticks{stroke:var(--gold-400);stroke-opacity:.22;stroke-width:1;stroke-dasharray:1.5 9}
.ring-outer{stroke:var(--gold-200);stroke-opacity:.5;stroke-width:1.4;stroke-dasharray:52 18}
.ring-mid{stroke:var(--gold-400);stroke-opacity:.32;stroke-width:1;stroke-dasharray:6 8}
.ring-inner{stroke:var(--gold-400);stroke-opacity:.5;stroke-width:1;stroke-dasharray:120 26}
/* Wide, faint stroke straddling the core edge -- a bloom around the rim
   without an SVG blur filter, which would cost a raster pass every frame. */
.ring-core-glow{fill:none;stroke:var(--gold-300);stroke-opacity:.07;stroke-width:14}
.ring-core{stroke:var(--gold-200);stroke-opacity:.8;stroke-width:1.4;fill:url(#core-plate)}
.ring-bevel{stroke:var(--gold-400);stroke-opacity:.3;stroke-width:.8}
.core-stop-1{stop-color:var(--core-fill-1)}
.core-stop-2{stop-color:var(--core-fill-2)}
.core-stop-3{stop-color:var(--core-fill-3)}

.medallion{
  position:relative;z-index:2;width:52%;text-align:center;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.55em;
  transform:translateZ(120px);
}
.medallion.is-roster{
  width:min(94%,46em);
  max-height:78%;
  padding:1.35em 1.45em 1.15em;
  gap:.75em;
  background:var(--ring-core-fill);
  border:1px solid rgba(201,162,69,.42);
  border-radius:14px;
  box-shadow:0 28px 70px rgba(5,4,9,.55);
  transform:translateZ(160px);
  overflow:hidden;
}
body.theme-white-gold .medallion.is-roster{
  box-shadow:0 24px 60px rgba(106,83,34,.16);
}
.medal-kicker{
  width:100%;flex:none;
  display:flex;align-items:center;justify-content:center;gap:.85em;
  font-size:var(--fs-small);color:var(--gold-300);
  letter-spacing:.3em;
}
/* Hairlines flank the label so it reads as a struck caption rather than a
   floating word. They fade outward, away from the text. */
.medal-kicker::before,.medal-kicker::after{
  content:"";flex:none;height:1px;width:2.6em;
  background:linear-gradient(90deg,transparent,var(--gold-400));
}
.medal-kicker::before{transform:scaleX(-1)}
/* The label's trailing letter-space already pads its right edge; shrinking
   the right gap by the same amount keeps the lockup optically centred. */
.medal-kicker::after{margin-left:-.3em}
.medal-names{
  width:70%;text-align:center;
  font-size:var(--fs-name);font-weight:500;line-height:1.28;color:var(--gold-100);
  white-space:nowrap;overflow:visible;
  padding:.08em .15em .22em;
}
/* Gilded fill for the one-line states (prize name, single winner). Rosters
   keep flat gold -- a gradient across a five-column board would leave the
   bottom rows noticeably darker than the top. */
.medal-names:not(.is-multi){
  background:linear-gradient(174deg,var(--gold-100) 0%,var(--gold-200) 40%,var(--gold-400) 100%);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  filter:var(--name-glow);
}

/* Rule between the name and its caption. Hidden for rosters, where the board
   already runs to the plate edge. */
.medal-rule{
  position:relative;flex:none;width:min(58%,13em);height:1px;margin:.45em 0;
  background:linear-gradient(90deg,transparent,var(--gold-400) 24%,var(--gold-400) 76%,transparent);
  opacity:.72;
}
.medal-rule::after{
  content:"";position:absolute;left:50%;top:50%;width:6px;height:6px;
  transform:translate(-50%,-50%) rotate(45deg);
  background:var(--gold-300);box-shadow:0 0 10px rgba(201,162,69,.6);
}
.medallion.is-roster .medal-rule{display:none}
.medal-names.is-multi{
  width:100%;
  font-size:var(--fs-name-multi);white-space:normal;line-height:1.35;
  max-height:8.6em;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--gold-400) transparent;
}
.medal-names.is-dense{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:.75em;row-gap:.12em;
  font-size:var(--fs-name-dense);line-height:1.28;
  width:92%;max-height:8.2em;
}
.medal-names.is-board{
  display:grid;grid-template-columns:repeat(var(--cols,3),minmax(0,1fr));
  column-gap:.55em;row-gap:.22em;
  font-size:clamp(11px,calc(2.05vmin - .14vmin * var(--cols, 3)),20px);
  line-height:1.28;font-weight:500;
  width:100%;max-height:none;flex:1;min-height:0;overflow-y:auto;
}
.medal-names .n{display:block;line-height:inherit;padding-bottom:.08em}
.medal-names.is-dense .n,.medal-names.is-board .n{
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.medal-sub{
  width:100%;text-align:center;flex:none;min-height:1.2em;
  font-size:var(--fs-small);color:var(--gold-300);
  letter-spacing:.16em;text-indent:.16em;
}

.app.projector .topbar-right,.app.projector .special-add,.app.projector .rail-note{opacity:0;pointer-events:none}
.app.projector .result-redraw{display:none}
.app.projector .topbar{background:none}
.app.projector .topbar{border-color:transparent}

@media (max-width:960px),(max-height:560px){
  :root{--ring-size:clamp(220px,42vmin,520px);--fs-name:clamp(22px,4.4vmin,48px)}
  .brand-hotel{font-size:clamp(14px,3.6vw,22px);letter-spacing:.1em;text-indent:.1em}
  .brand-meta{letter-spacing:.12em;gap:.4em}
  .brand-meta > span:not(.brand-rule):not(.brand-sep){margin-inline-end:-.12em}
  .layout{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);gap:1.4vmin}
  .rail-right{display:none}
  /* Compact layout: the wheel can fill the stage outright, leaving no headroom
     above or below the outer ring, so the crest would land on the prize rail. */
  .crest{display:none}
  .rail{max-height:24vh}
  .prize-list{flex-direction:row;overflow-x:auto;overflow-y:hidden;padding-bottom:4px}
  .prize{flex:0 0 auto;min-width:9em}
  .special-list{flex-direction:row;overflow-x:auto;overflow-y:hidden;max-height:none}
  .special{flex:0 0 auto;min-width:9em}
  .special-add{grid-template-columns:1fr 4.8em auto}
  .dashed-btn{grid-column:auto;white-space:nowrap;padding-inline:1em}
  .rail-note{display:none}
  .drawer-panel{width:100%;min-width:0}
}
