/* Shared controls. Layout belongs to the page; surfaces and states belong here.
   primary/secondary aliases keep dynamically created and guest controls consistent. */
@import url('./tokens.css');
:root {
 --ui-control-radius:12px;
 --ui-control-height:48px;--ui-control-small-height:36px;
}
.ui-button,.primary,.secondary {
 display:inline-flex;align-items:center;justify-content:center;gap:8px;
 min-width:44px;min-height:var(--ui-control-height);padding:12px 18px;
 border:1px solid var(--ui-border);border-radius:var(--ui-control-radius);
 background:var(--ui-surface);color:var(--ui-text);box-shadow:var(--ui-control-shadow);
 font-family:var(--font-ui);font-size:14px;font-weight:650;line-height:1.3;
 text-align:center;text-decoration:none;cursor:pointer;touch-action:manipulation;
 transition:background 120ms ease,border-color 120ms ease,transform 90ms ease;
}
.primary,.ui-button[data-variant=primary] {background:var(--ui-action);border-color:var(--ui-action);color:var(--ui-action-ink)}
.ui-button[data-variant=quiet] {background:transparent;border-color:transparent;box-shadow:none}
.ui-button svg {width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;flex:none}
@media(hover:hover) {
 :is(.ui-button,.primary,.secondary):not(:disabled):hover {background:var(--ui-surface-hover)}
 :is(.primary,.ui-button[data-variant=primary]):not(:disabled):hover {background:var(--ui-action-hover);border-color:var(--ui-action-hover)}
}
:is(.ui-button,.primary,.secondary):not(:disabled):active {transform:translateY(1px);background:var(--ui-surface-hover);box-shadow:none}
:is(.primary,.ui-button[data-variant=primary]):not(:disabled):active {background:var(--ui-action-pressed);border-color:var(--ui-action-pressed)}
:is(.ui-button,.primary,.secondary):focus-visible {outline:3px solid var(--ui-focus);outline-offset:3px}
:is(.ui-button,.primary,.secondary):disabled {opacity:1;cursor:default;background:var(--ui-disabled);border-color:var(--ui-disabled);color:var(--ui-disabled-text);box-shadow:none;transform:none}
.ui-button[data-size=small] {position:relative;min-height:var(--ui-control-small-height);padding:7px 12px;border-radius:8px;font-size:13px}
/* A compact visible surface with a 44px pointer target. Leave at least 8px
   between vertically adjacent small buttons so their hit areas do not overlap. */
.ui-button[data-size=small]::after {content:"";position:absolute;inset:-4px 0}
.ui-button[data-layout=stack] {flex-direction:column;gap:5px;min-height:72px;font-size:12px}
.ui-button[data-layout=icon] {width:44px;height:44px;min-height:44px;padding:10px}
.ui-button[data-width=full] {width:100%}
.ui-button[data-layout=icon][data-shape=circle] {border-radius:50%}
.ui-scroll-row {min-width:0;overflow-x:auto;touch-action:pan-x;overscroll-behavior-x:contain;user-select:none}
.ui-scroll-row[data-dragging=true],.ui-scroll-row[data-dragging=true] * {cursor:grabbing}
@media(prefers-reduced-motion:reduce) {.ui-button,.primary,.secondary {transition:none}}
@media(forced-colors:active) {
 .ui-button,.primary,.secondary {background:ButtonFace;color:ButtonText;border:1px solid ButtonText;box-shadow:none}
 :is(.ui-button,.primary,.secondary):disabled {color:GrayText;border-color:GrayText}
 :is(.ui-button,.primary,.secondary):focus-visible {outline-color:Highlight}
}

/* Compact line navigation: Collection on the left, the brand in the middle, the
   controls toggle on the right. Each is a quiet 44px hit area around a 21px line icon. */

.ui-header-action {
 display:inline-flex;align-items:center;justify-content:center;flex:none;
 width:44px;min-width:44px;height:44px;min-height:44px;padding:0;border:0;border-radius:12px;
 background:transparent;color:var(--ui-icon);cursor:pointer;filter:var(--ui-header-icon-shadow);touch-action:manipulation;
}
.ui-header-action img {display:block;object-fit:contain;pointer-events:none;user-select:none}
.ui-header-action svg {display:block;width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}
.ui-header-action:not(:disabled):active {transform:translateY(1px)}
.ui-header-action:focus-visible {outline:2px solid var(--ui-focus);outline-offset:2px}
.ui-header-action:disabled {opacity:.45;cursor:default}
/* Something new waits behind this control (a keycap drawn since Collection was last opened). */
.ui-header-action {position:relative}
.ui-header-dot {position:absolute;top:9px;right:9px;width:8px;height:8px;border-radius:50%;background:var(--ui-action);box-shadow:0 0 0 2px var(--ui-stage-mid);pointer-events:none}
/* The same mark on a dock action (the button is positioned by its page). */
.ui-action-dot {position:absolute;top:7px;right:9px;width:8px;height:8px;border-radius:50%;background:var(--ui-action);box-shadow:0 0 0 2px var(--ui-surface);pointer-events:none}
/* The brand lockup in a row, for the top bar: small, and the symbol only just taller than the logotype. */
.ui-brand-lockup[data-layout=row] {flex-direction:row;justify-content:center;gap:7px;flex:1;min-width:0;color:var(--brand-ink,var(--ui-icon))}
.ui-brand-lockup[data-layout=row] .ui-brand-symbol {width:auto;height:13px}
.ui-brand-lockup[data-layout=row] .ui-brand-logotype {width:auto;max-width:none;height:11px}
.ui-brand-lockup[data-layout=row] svg {width:auto;height:100%}
/* Ticket count: a fixed-width cell, so the progress bar beside it never moves as the
   balance changes on the same device. Four digits fit at full size; longer balances
   shrink to stay inside the cell. */
.ui-ticket-count {--ui-ticket-font:20px;--ui-ticket-scale:1;display:flex;align-items:center;flex:none;gap:5px;width:94px;color:var(--ui-text)}
.ui-ticket-count img {display:block;flex:none;width:28px;height:22px;object-fit:contain}
.ui-ticket-count b {flex:1;min-width:0;font-size:calc(var(--ui-ticket-font) * var(--ui-ticket-scale));font-weight:800;line-height:1;font-variant-numeric:tabular-nums;letter-spacing:-.01em;white-space:nowrap}
/* Manrope 800 tabular digits are about 0.61em wide, so the 50px number box holds four
   at 20px; each further digit steps the size down to keep the count inside the cell.
   Pages scale the whole cell with --ui-ticket-scale; the digit steps stay here. */
.ui-ticket-count[data-digits="5"] {--ui-ticket-font:16px}
.ui-ticket-count[data-digits="6"] {--ui-ticket-font:13.5px}
.ui-ticket-count[data-digits="7"] {--ui-ticket-font:11.5px}
.ui-ticket-count[data-digits="8"] {--ui-ticket-font:10px}
.ui-ticket-count[data-digits="9"] {--ui-ticket-font:9px}
.ui-ticket-count[data-digits="10"] {--ui-ticket-font:8px}
/* A rainbow turning around the border says a ticket is ready to spend. The button's own
   surface moves to ::after so the gradient shows only in the 2px ring; hover, pressed and
   disabled keep their usual fills. */
.ui-button[data-halo=rainbow] {position:relative;isolation:isolate;overflow:hidden;background:transparent;border-color:transparent}
.ui-button[data-halo=rainbow]::before {content:"";position:absolute;inset:-150%;z-index:-2;background:var(--ui-draw-halo);animation:ui-halo-turn 2.6s linear infinite}
.ui-button[data-halo=rainbow]::after {content:"";position:absolute;inset:2px;z-index:-1;border-radius:calc(var(--ui-control-radius) - 2px);background:var(--ui-action);transition:background 120ms ease}
@media(hover:hover) {.ui-button[data-halo=rainbow]:not(:disabled):hover {background:transparent}.ui-button[data-halo=rainbow]:not(:disabled):hover::after {background:var(--ui-action-hover)}}
.ui-button[data-halo=rainbow]:not(:disabled):active {background:transparent}
.ui-button[data-halo=rainbow]:not(:disabled):active::after {background:var(--ui-action-pressed)}
@keyframes ui-halo-turn {to {transform:rotate(1turn)}}
@media(prefers-reduced-motion:reduce) {.ui-button[data-halo=rainbow]::before {animation:none}}
@media(forced-colors:active) {
 .ui-header-action {border:1px solid ButtonText;background:Canvas;filter:none;box-shadow:none}
 .ui-header-dot,.ui-action-dot {background:Highlight;box-shadow:none}
 .ui-button[data-halo=rainbow] {background:ButtonFace;border-color:ButtonText}
 .ui-button[data-halo=rainbow]::before,.ui-button[data-halo=rainbow]::after {display:none}
}
/* Shared settings controls. Use with native buttons, labels and details. */
:root {--ui-panel-radius:18px;}
.ui-panel {padding:18px;border:1px solid var(--ui-border);border-radius:var(--ui-panel-radius);background:var(--ui-panel-fill);text-align:left}
.ui-panel h3 {margin:0;font-size:14px;font-weight:750;line-height:1.4}
.ui-row {display:flex;align-items:center;justify-content:space-between;gap:12px}
.ui-row>div {min-width:0}
.ui-row>.ui-button {flex-shrink:0}
.ui-caption {margin:0;color:var(--color-muted);font-size:10px;font-weight:750;letter-spacing:.13em;line-height:1.5}
.ui-description {margin:4px 0 0;color:var(--color-muted);font-size:12px;font-weight:400;line-height:1.6}
.ui-badge {display:inline-flex;align-items:center;gap:4px;padding:4px 8px;border-radius:6px;background:var(--ui-soft-fill);color:var(--color-muted);font-size:10px;font-weight:650;line-height:1.4;white-space:nowrap}
.ui-badge[data-tone=selected] {background:var(--ui-selected-fill);color:var(--ui-selected-ink)}
.ui-choice {position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:68px;min-width:44px;padding:12px 8px;border:1px solid var(--ui-border);border-radius:var(--ui-control-radius);background:var(--ui-surface);color:var(--ui-text);font:inherit;cursor:pointer;touch-action:manipulation}
.ui-choice strong {font-size:15px;font-weight:750}
.ui-choice span {font-size:11px;color:var(--color-muted)}
.ui-choice[aria-pressed=true] {background:var(--color-action);border-color:var(--color-action);color:var(--ui-selection-ink)}
.ui-choice[aria-pressed=true] span {color:var(--ui-selection-ink)}
/* Compact choice: for dense grids (the nine switches), where a note may wrap to two lines. */
.ui-choice[data-size=compact] {min-height:64px;padding:10px 6px;text-align:center}
.ui-choice[data-size=compact] strong {font-size:14px}
.ui-choice[data-size=compact] span {line-height:1.3}
.ui-choice:disabled {background:var(--ui-disabled);color:var(--ui-disabled-text);cursor:default}
/* Tabs keep navigation separate from the scrolling contents of each panel. */
.ui-tabs {display:flex;gap:4px;padding:4px;border:1px solid var(--ui-border);border-radius:14px;background:var(--ui-soft-fill)}
.ui-tab {flex:1;min-width:0;min-height:44px;border:0;border-radius:10px;padding:10px 16px;background:transparent;color:var(--ui-muted);font:inherit;font-size:13px;font-weight:750;cursor:pointer;touch-action:manipulation}
.ui-tab[aria-selected=true] {background:var(--ui-selection);color:var(--ui-selection-ink)}
.ui-tab:focus-visible {outline:2px solid var(--ui-focus);outline-offset:2px}
@media(hover:hover) {.ui-tab:not([aria-selected=true]):hover {background:var(--ui-surface-hover);color:var(--ui-text)}}
.ui-tab:active {transform:translateY(1px)}
@media(forced-colors:active) {.ui-tab[aria-selected=true] {background:Highlight;color:HighlightText;outline:1px solid Highlight}}
.theme-option.ui-choice {width:100%;flex-direction:row;justify-content:flex-start;gap:12px;padding:12px;text-align:left}
.theme-option.ui-choice:disabled {opacity:1;background:var(--ui-surface);color:var(--ui-muted)}
.theme-option.ui-choice i {width:48px;height:48px;flex:none;border-radius:9px;background:#e8e9e6 url('/public/assets/themes/mood-thumbnails/neutral.jpg') center/cover no-repeat;box-shadow:inset 0 0 0 1px #00000015}
.theme-option.ui-choice[data-mood=conservatory-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/conservatory-v1.jpg')}
.theme-option.ui-choice[data-mood=sunlit-chalk-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/sunlit-chalk-v1.jpg')}
.theme-option.ui-choice[data-mood=color-atelier-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/color-atelier-v1.jpg')}
.theme-option.ui-choice[data-mood=walnut-desk-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/walnut-desk-v1.jpg')}
.theme-option.ui-choice[data-mood=jelly-lab-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/jelly-lab-v1.jpg')}
.theme-option.ui-choice[data-mood=metal-workbench-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/metal-workbench-v1.jpg')}
.theme-option.ui-choice[data-mood=dessert-cafe-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/dessert-cafe-v1.jpg')}
.theme-option.ui-choice[data-mood=night-study-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/night-study-v1.jpg')}
.theme-option.ui-choice[data-mood=control-room-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/control-room-v1.jpg')}
.theme-option.ui-choice[data-mood=retro-arcade-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/retro-arcade-v1.jpg')}
.theme-option.ui-choice[data-mood=living-corner-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/living-corner-v1.jpg')}
.theme-option.ui-choice[data-mood=pattern-studio-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/pattern-studio-v1.jpg')}
.theme-option.ui-choice[data-mood=prism-gallery-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/prism-gallery-v1.jpg')}
.theme-option.ui-choice[data-mood=photo-greenhouse-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/photo-greenhouse-v1.jpg')}
.theme-option.ui-choice[data-mood=rainy-window-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/rainy-window-v1.jpg')}
.theme-option.ui-choice[data-mood=moonlit-garden-v1] i {background-image:url('/public/assets/themes/mood-thumbnails/moonlit-garden-v1.jpg')}
.theme-option.ui-choice strong,.theme-option.ui-choice small {display:block;color:inherit}
.theme-option.ui-choice>span {color:inherit;min-width:0}
.theme-option.ui-choice strong {font-size:13px}
.theme-option.ui-choice small {font-size:11px;margin-top:3px;line-height:1.5}
.ui-select {display:block;width:100%;min-height:48px;margin-top:8px;padding:10px 12px;border:1px solid var(--ui-border);border-radius:var(--ui-control-radius);background:var(--ui-surface);color:var(--ui-text);font:inherit;font-size:16px;cursor:pointer}
.ui-field-label {font-size:12px;font-weight:650;color:var(--ui-text);letter-spacing:normal;line-height:1.5}
/* Text entry: the same surface as ui-select. 16px text so iOS does not zoom on focus. */
.ui-text-field {display:block;box-sizing:border-box;width:100%;min-height:48px;margin-top:8px;padding:10px 12px;border:1px solid var(--ui-border);border-radius:var(--ui-control-radius);background:var(--ui-surface);color:var(--ui-text);font:inherit;font-size:16px;line-height:1.5}
textarea.ui-text-field {min-height:112px;resize:vertical}
.ui-text-field::placeholder {color:var(--color-muted)}
.ui-text-field:focus-visible {outline:3px solid var(--ui-focus);outline-offset:2px}
.ui-range {appearance:none;-webkit-appearance:none;display:block;width:100%;height:44px;min-height:44px;margin:0;background:transparent;accent-color:var(--ui-action);cursor:pointer;--ui-range-rest:var(--ui-border)}
.ui-range::-webkit-slider-runnable-track {height:6px;border:0;border-radius:6px;background:linear-gradient(to right,var(--ui-action) 0 var(--ui-range-fill,80%),var(--ui-range-rest) var(--ui-range-fill,80%) 100%)}
.ui-range::-webkit-slider-thumb {-webkit-appearance:none;appearance:none;width:16px;height:16px;margin-top:-5px;border:0;border-radius:50%;background:var(--ui-action)}
.ui-range::-moz-range-track {height:6px;border:0;border-radius:6px;background:var(--ui-range-rest)}
.ui-range::-moz-range-progress {height:6px;border-radius:6px;background:var(--ui-action)}
.ui-range::-moz-range-thumb {width:16px;height:16px;border:0;border-radius:50%;background:var(--ui-action)}
@media(forced-colors:active) {.ui-range {--ui-action:Highlight;--ui-range-rest:GrayText}.ui-choice[aria-pressed=true] span {color:CanvasText}}
.ui-disclosure {font-size:12px;text-align:left}
.ui-disclosure+.ui-disclosure {border-top:1px solid var(--ui-border)}
.ui-disclosure summary {display:flex;align-items:center;gap:8px;min-height:52px;cursor:pointer;list-style:none;font-size:13px;font-weight:650}
.ui-disclosure summary::-webkit-details-marker {display:none}
.ui-disclosure summary::after {content:'+';margin-left:auto;color:var(--color-muted);font-size:20px;font-weight:400}
.ui-disclosure[open] summary::after {content:'−'}
.ui-disclosure summary .ui-description {margin:0;font-size:10px}
.ui-disclosure>div {padding:0 0 14px;color:var(--color-muted);line-height:1.7}
.ui-disclosure p {margin:0 0 10px}
.ui-disclosure p:last-child {margin-bottom:0}
:is(.ui-choice,.ui-disclosure summary):focus-visible {outline:3px solid var(--ui-focus);outline-offset:3px}
:is(input,select,textarea):focus-visible {outline:0;box-shadow:0 0 0 3px var(--ui-focus-halo)}
dialog[tabindex="-1"]:focus {outline:0}
@media(hover:hover) {.ui-choice:not(:disabled):hover {border-color:var(--ui-focus)}.ui-disclosure summary:hover {color:var(--ui-focus)}}
@media(forced-colors:active) {.ui-panel,.ui-choice,.ui-select,.ui-badge {background:Canvas;color:CanvasText;border:1px solid ButtonText}.ui-choice[aria-pressed=true] {outline:2px solid Highlight}}

/* Non-interactive selected-item marker. Pair with the control's aria-pressed state. */
.ui-current-mark {display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:none;border:1px solid var(--ui-selected-border);border-radius:50%;background:var(--ui-selected-fill);color:var(--ui-selected-ink);pointer-events:none}
.ui-current-mark svg {display:block;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
@media(forced-colors:active) {.ui-current-mark {background:Canvas;color:Highlight;border-color:Highlight}}
/* Keep text labels visible: rarity is never communicated by color alone. */
[data-rarity=common] {--rarity-ink:var(--rarity-common-ink);--rarity-accent:var(--rarity-common-accent);--rarity-surface:var(--rarity-common-surface);--rarity-line:var(--rarity-common-line)}
[data-rarity=uncommon] {--rarity-ink:var(--rarity-uncommon-ink);--rarity-accent:var(--rarity-uncommon-accent);--rarity-surface:var(--rarity-uncommon-surface);--rarity-line:var(--rarity-uncommon-line)}
[data-rarity=rare] {--rarity-ink:var(--rarity-rare-ink);--rarity-accent:var(--rarity-rare-accent);--rarity-surface:var(--rarity-rare-surface);--rarity-line:var(--rarity-rare-line)}
[data-rarity=epic] {--rarity-ink:var(--rarity-epic-ink);--rarity-accent:var(--rarity-epic-accent);--rarity-surface:var(--rarity-epic-surface);--rarity-line:var(--rarity-epic-line)}
[data-rarity=legendary] {--rarity-ink:var(--rarity-legendary-ink);--rarity-accent:var(--rarity-legendary-accent);--rarity-surface:var(--rarity-legendary-surface);--rarity-line:var(--rarity-legendary-line)}
[data-rarity=mythic] {--rarity-ink:var(--rarity-mythic-ink);--rarity-accent:var(--rarity-mythic-accent);--rarity-surface:var(--rarity-mythic-surface);--rarity-line:var(--rarity-mythic-line)}
.ui-collectible {min-width:0;padding:8px 6px;border:1px solid var(--ui-collectible-border);border-radius:12px;background:var(--ui-collectible-surface);text-align:center}
.ui-collectible .ui-collectible-name {display:block;margin:6px 0 4px;font-size:11px;font-weight:700;line-height:1.35;color:var(--rarity-ink);overflow-wrap:anywhere}
.ui-rarity {display:inline-flex;align-items:center;justify-content:center;max-width:100%;padding:4px 6px;border-radius:6px;background:var(--rarity-surface);color:var(--rarity-ink);font-size:10px;font-weight:700;line-height:1.3;white-space:nowrap}
.ui-collectible .ui-collectible-count {display:block;margin:4px 0 0;font-size:10px;font-weight:400;line-height:1.5;color:var(--ui-collectible-muted)}
@media(forced-colors:active) {.ui-collectible,.ui-rarity {background:Canvas;border:1px solid CanvasText;color:CanvasText}.ui-collectible .ui-collectible-name {color:CanvasText}}

.ui-collectible .art {display:block;width:100%;max-width:100px;height:auto;aspect-ratio:1;margin:auto}
.ui-collectible.is-missing {position:relative;min-height:150px}
.ui-collectible.is-missing > * {display:none}
.ui-collectible.is-missing::before,.ui-collectible.is-missing::after {content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:calc(100% - 12px);max-width:100px;aspect-ratio:1;pointer-events:none}
.ui-collectible.is-missing::before {background:var(--ui-placeholder-face);mask:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20100%20100%22%3E%3Cpath%20d%3D%22M23%207h54c7%200%2010%204%2012%2011l7%2062c1%208-3%2013-11%2013H15C7%2093%203%2088%204%2080l7-62c2-7%205-11%2012-11Z%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat}
.ui-collectible.is-missing::after {background:var(--ui-placeholder-ink);mask:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20100%20100%22%3E%3Cpath%20d%3D%22M40%2039c0-12%2021-13%2021%200%200%208-11%208-11%2017%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%226%22%20stroke-linecap%3D%22round%22%2F%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2267%22%20r%3D%223.2%22%2F%3E%3C%2Fsvg%3E") center/85% no-repeat}
@media(forced-colors:active) {.ui-collectible.is-missing {border-color:CanvasText}}

.ui-button.ui-filter {position:relative;min-height:36px;padding:6px 12px;border-radius:999px;font-size:11px;white-space:nowrap;flex:none}
.ui-button.ui-filter::after {content:"";position:absolute;inset:-4px 0}
.ui-button.ui-filter[aria-pressed=true] {background:var(--color-action);border-color:var(--color-action);color:var(--ui-selection-ink)}
@media(hover:hover) {.ui-button.ui-filter[aria-pressed=true]:hover {background:var(--color-action-bottom)}}
@media(forced-colors:active) {.ui-button.ui-filter[aria-pressed=true] {background:Highlight;color:HighlightText;border-color:Highlight}}

/* Compact filters preserve the full 44px touch target. */
.ui-select[data-size=compact] {min-width:0;min-height:44px;height:44px;margin:0;padding:8px;font-size:12px;text-overflow:ellipsis}
.ui-button[data-size=compact] {min-height:44px;padding:8px 10px;font-size:12px;gap:5px}
.ui-button[data-size=compact] svg {width:18px;height:18px}
.ui-empty-state {margin:0;padding:18px 12px;border:1px solid var(--ui-border);border-radius:var(--ui-control-radius);background:var(--ui-soft-fill);color:var(--color-muted);font-size:12px;text-align:center;line-height:1.6}
.ui-confirm {width:calc(100% - 32px);max-width:380px;max-height:calc(100dvh - 32px);overflow-y:auto;margin:auto;padding:24px;border:1px solid var(--ui-border);border-radius:var(--radius-sheet);background:var(--ui-surface);color:var(--ui-text);box-shadow:0 18px 60px var(--ui-shadow-strong)}
.ui-confirm::backdrop {background:var(--ui-backdrop);backdrop-filter:blur(4px)}
.ui-confirm h2 {margin:0 0 10px;font-size:21px;line-height:1.3;letter-spacing:-.5px}
.ui-confirm p {margin:0;color:var(--color-muted);font-size:13px;line-height:1.65}
.ui-confirm-actions {display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:24px}
.ui-confirm-actions:not(:has(> :not([hidden]) ~ :not([hidden]))) {grid-template-columns:1fr}
@media(forced-colors:active) {.ui-confirm,.ui-empty-state {background:Canvas;color:CanvasText;border-color:CanvasText}}

/* Title artwork and loading sequence. */
.ui-title-swipe-stack {position:relative;overflow:hidden}
.ui-title-swipe-stack.is-swiping>.ui-title-screen,.ui-title-swipe-stack.is-swiping>.ui-title-swipe-next {position:absolute;inset:0;width:100%;height:100%;margin:0;pointer-events:none}
.ui-title-swipe-stack.is-swiping>.ui-title-swipe-next {transform:translateY(100%)}
.ui-title-screen {position:relative;height:100%;overflow:hidden;isolation:isolate;background:var(--ui-art-surface);color:var(--ui-on-art)}
.ui-title-background {position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;pointer-events:none;user-select:none}
.ui-brand-lockup {display:flex;flex-direction:column;align-items:center;gap:24px;color:var(--ui-on-art)}
.ui-brand-lockup span {display:block;flex:none}
.ui-brand-symbol {width:106px}
.ui-brand-logotype {width:260px;max-width:76vw}
.ui-brand-lockup svg {display:block;width:100%;height:auto;fill:currentColor;stroke:none}
.ui-brand-lockup svg :is(path,polygon,rect,circle,ellipse) {fill:currentColor;stroke:none}
.ui-title-screen>.ui-brand-lockup {position:absolute;top:31%;left:50%;transform:translate(-50%,-50%);width:100%;padding:0 24px}
.ui-title-screen .ui-brand-lockup.is-loaded .ui-brand-symbol {animation:ui-title-symbol-in 800ms cubic-bezier(.16,1,.3,1) both}
.ui-title-screen .ui-brand-lockup.is-loaded .ui-brand-logotype {animation:ui-title-wordmark-in 850ms 180ms cubic-bezier(.16,1,.3,1) both}
.ui-title-loading {position:absolute;top:68%;left:50%;width:min(250px,calc(100% - 64px));transform:translate(-50%,-50%);display:grid;gap:14px}
.ui-title-progress {height:7px;border:1px solid color-mix(in srgb,var(--ui-on-art) 60%,transparent);border-radius:99px;background:color-mix(in srgb,var(--ui-on-art) 19%,transparent);box-shadow:0 1px 12px var(--ui-art-shadow);overflow:hidden}
.ui-title-progress-fill {display:block;width:100%;height:100%;border-radius:inherit;background:var(--ui-on-art);transform:scaleX(0);transform-origin:left;transition:transform 420ms cubic-bezier(.2,.7,.2,1)}
.ui-title-status {min-height:21px;margin:0;font-family:var(--font-ui);font-size:12px;font-weight:650;letter-spacing:.045em;line-height:1.5;text-align:center;color:var(--ui-on-art);text-shadow:0 1px 8px var(--ui-art-shadow)}
.ui-title-screen[data-state=ready] .ui-title-progress-fill {box-shadow:0 0 16px var(--ui-on-art)}
@keyframes ui-title-symbol-in {from {opacity:0;transform:translateY(22px) scale(.9)}to {opacity:1;transform:translateY(0) scale(1)}}
@keyframes ui-title-wordmark-in {from {opacity:0;transform:translateY(16px)}to {opacity:1;transform:translateY(0)}}
@media(max-height:500px) {.ui-title-screen .ui-brand-lockup {gap:14px}.ui-title-screen .ui-brand-symbol {width:76px}.ui-title-screen .ui-brand-logotype {width:220px}}
@media(prefers-reduced-motion:reduce) {.ui-title-screen .ui-brand-lockup.is-loaded .ui-brand-symbol,.ui-title-screen .ui-brand-lockup.is-loaded .ui-brand-logotype {animation:none}.ui-title-progress-fill {transition:none}}
@media(forced-colors:active) {.ui-title-screen {background:Canvas;color:CanvasText}.ui-title-background {display:none}.ui-title-screen .ui-brand-lockup,.ui-title-status {color:CanvasText}.ui-title-progress {border-color:CanvasText;background:Canvas}.ui-title-progress-fill {background:Highlight}}

/* Interactive art preview: same physical renderer and gesture as the play board. */
.ui-mount-preview {display:block;position:relative;width:160px;height:170px;margin:12px auto;padding:0;border:0;border-radius:16px;background:transparent;box-shadow:none;cursor:pointer;touch-action:manipulation}
.ui-mount-preview canvas {display:block;width:100%;height:100%;pointer-events:none}
.ui-mount-preview:focus-visible {outline:3px solid var(--ui-focus);outline-offset:3px}
.ui-light-preview {width:100%;height:auto;max-width:336px;border-radius:16px;overflow:hidden;touch-action:none}
.ui-light-preview canvas {width:100%;height:auto}

/* Reward history: rarity belongs to the border; selection uses a separate white ring. */
.ui-reward-history {min-width:0;color:var(--gacha-ink);--reward-surface:var(--gacha-reward);--reward-focus:var(--gacha-reward-ring)}
.ui-reward-nav {display:flex;align-items:center;justify-content:center;gap:12px;min-height:44px}
.ui-reward-nav span {min-width:145px;font-size:11px;text-align:center;color:var(--gacha-muted);font-variant-numeric:tabular-nums}
.ui-reward-nav button {display:grid;place-items:center;width:44px;height:44px;min-height:44px;padding:0;border:0;border-radius:50%;background:transparent;color:inherit;font-size:27px;box-shadow:none}
.ui-reward-nav button:disabled {opacity:.25;cursor:default}
.ui-reward-pages {display:flex;width:100%;overflow-x:auto;overflow-y:hidden;scroll-snap-type:none;overscroll-behavior-x:contain;scrollbar-width:none;touch-action:pan-x pan-y;cursor:grab}
.ui-reward-pages::-webkit-scrollbar {display:none}
.ui-reward-pages[data-dragging=true] {scroll-snap-type:none;cursor:grabbing}
.ui-reward-page {flex:0 0 100%;min-width:0;padding:4px 6px 6px}
.ui-reward-grid {display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:7px;max-width:300px;margin:auto}
.ui-reward-card {position:relative;display:block;aspect-ratio:1;min-width:44px;min-height:44px;width:100%;padding:3px;border:2px solid var(--rarity-accent);border-radius:9px;background:var(--reward-surface);box-shadow:none;touch-action:pan-x pan-y}
.ui-reward-card[aria-pressed=true] {outline:2px solid var(--reward-focus);outline-offset:2px}
.ui-reward-card .art {display:block;width:100%;height:auto;aspect-ratio:1;margin:0;background:none;border-radius:4px;pointer-events:none}
.ui-reward-card:focus-visible,.ui-reward-nav button:focus-visible,.ui-reward-pages:focus-visible {outline:3px solid var(--ui-focus);outline-offset:2px}
@media(hover:hover){.ui-reward-card:hover {background:var(--gacha-surface-hover)}.ui-reward-nav button:not(:disabled):hover {background:var(--gacha-quiet-hover)}}
@media(forced-colors:active){.ui-reward-history {color:CanvasText;--reward-surface:Canvas;--reward-focus:Highlight}.ui-reward-card {border-color:ButtonText}.ui-reward-nav span {color:CanvasText}}

/* Shared curve editor: gacha and keycap mounting use the same handles and states. */
.bezier-editor{border:1px solid var(--editor-border);border-radius:14px;padding:18px;margin:24px 0;background:var(--editor-surface)}
.bezier-editor h2{font-size:17px;margin:0 0 8px}.bezier-editor>label{font-size:12px;color:var(--editor-text)}
.bezier-editor select{margin-bottom:12px}.curve-mode{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:11px}
.curve-mode label{display:flex;align-items:center;gap:5px}.curve-mode input{accent-color:var(--editor-accent)}
#curve-mode{color:var(--editor-accent);font-size:10px}
#curve-graph{display:block;width:100%;height:auto;background:var(--editor-paper);border:1px solid var(--editor-border);border-radius:9px;margin:14px 0;touch-action:none;user-select:none}
#curve-graph text{fill:var(--editor-muted);font-size:11px}.curve-grid path{fill:none;stroke:var(--editor-grid);stroke-width:1}
.curve-diagonal{stroke:var(--editor-border);stroke-dasharray:3 5;fill:none}.curve-arm{stroke:var(--editor-line);stroke-width:1.5}
.curve-path{fill:none;stroke:var(--editor-accent);stroke-width:3;stroke-linecap:round}
.curve-origin,.curve-end{fill:var(--editor-point)}.curve-playhead{fill:var(--ui-highlight);stroke:var(--editor-accent);stroke-width:2;pointer-events:none}
.handle-dot{fill:var(--editor-accent);stroke:var(--editor-field);stroke-width:2}.handle-1 .handle-dot{fill:var(--editor-second)}
.curve-handle{cursor:grab;outline:none}.curve-handle:active{cursor:grabbing}.curve-handle:focus .handle-dot{stroke:var(--ui-highlight);stroke-width:3}
.is-legacy .curve-arm{stroke-dasharray:4 4;opacity:.5}.is-legacy .handle-dot{opacity:.55}
.curve-numbers{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}
.curve-numbers label{font-size:11px;color:var(--editor-muted);display:flex;flex-direction:column;gap:5px}
.curve-numbers input,#curve-css{width:100%;min-width:0;color:var(--editor-accent);background:var(--editor-field);border:1px solid var(--editor-border);border-radius:6px;padding:7px;font-size:12px}
.curve-css-label{display:block;margin:12px 0 6px}#curve-css{font-family:monospace}
.curve-presets{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:12px 0}
.curve-presets button{font-size:11px}.bezier-editor>.row button{flex:1;font-size:11px}
#curve-note{min-height:54px;margin-bottom:0}
.control input:disabled{opacity:.4}.curve-numbers input:focus-visible,#curve-css:focus-visible{outline:0;box-shadow:0 0 0 3px var(--ui-focus-halo)}

/* Editable numeric values and motion tracks accompany the shared range controls. */
.ui-number{min-width:0;min-height:44px;border:1px solid var(--ui-border);border-radius:8px;background:var(--ui-surface);color:var(--ui-text);padding:8px;font:inherit;font-size:13px;font-variant-numeric:tabular-nums}
.ui-number:focus-visible{outline:0;box-shadow:0 0 0 3px var(--ui-focus-halo)}
.motion-tracks{display:grid;gap:5px;padding:4px 0;position:relative}
.motion-track{height:19px;position:relative;background:var(--ui-soft-fill);border-radius:5px;overflow:hidden}
.motion-track>span{position:absolute;top:0;bottom:0;min-width:2px;border-radius:5px;background:var(--ui-track-press)}
.motion-track[data-track=lift]>span{background:var(--ui-track-lift)}.motion-track[data-track=fade]>span{background:var(--ui-track-fade)}
.motion-track>small{position:relative;padding-left:7px;font-size:10px;line-height:19px;color:var(--ui-text)}
.motion-cue{position:absolute;top:0;bottom:0;border-left:2px dashed var(--ui-action);pointer-events:none}

.motion-track[data-selected=true]{outline:1px solid var(--ui-action);outline-offset:1px}
@media(forced-colors:active){:is(input,select,textarea):focus-visible,.ui-number:focus-visible,.curve-numbers input:focus-visible,#curve-css:focus-visible{outline:2px solid Highlight;outline-offset:2px;box-shadow:none}}

/* Native controls and text selection share the active theme, including dark UI. */
[data-color-scheme=light] {color-scheme:light}
[data-color-scheme=dark] {color-scheme:dark}
:is(input,select,textarea) {caret-color:var(--ui-text);accent-color:var(--ui-action)}
::placeholder {color:var(--ui-muted);opacity:1}
::selection {background:var(--ui-selection);color:var(--ui-selection-ink)}

/* Reward signals (2026-09-30). Two ways a draw says it gave more than a keycap.

   Sound mark: a keycap that makes its own sound wears this disc on its corner wherever
   the keycap is shown large. Quiet by default (surface disc, muted glyph); data-tone=new
   paints it in the action colour for a sound the player did not have, and data-burst
   plays the arrival once: the disc pops in, two rings ripple out and the bars swing like
   a level meter for about a second. --size sets the disc (30–44px); the page positions
   it. The surface it sits on can remap --mark-* (the gacha stage does). */
.ui-sound-mark {--size:36px;position:relative;display:grid;place-items:center;flex:none;width:var(--size);height:var(--size);border-radius:50%;background:var(--mark-surface,var(--ui-surface));color:var(--mark-ink,var(--ui-muted));box-shadow:0 0 0 2px var(--mark-ring,var(--ui-border)),0 4px 12px var(--mark-shadow,var(--ui-shadow))}
.ui-sound-mark svg {display:block;width:calc(var(--size) * .56);height:calc(var(--size) * .56);fill:none;stroke:currentColor;stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
.ui-sound-mark[data-tone=new] {background:var(--mark-accent,var(--ui-action));color:var(--mark-accent-ink,var(--ui-action-ink));box-shadow:0 0 0 2px var(--mark-accent-ring,var(--ui-highlight)),0 6px 18px var(--mark-shadow,var(--ui-shadow-strong))}
.ui-sound-mark::before,.ui-sound-mark::after {content:"";position:absolute;inset:-2px;border-radius:50%;border:2px solid var(--mark-accent,var(--ui-action));opacity:0;pointer-events:none}
.ui-sound-mark[data-burst] {animation:ui-sound-mark-pop 640ms cubic-bezier(.22,1.4,.36,1) both}
.ui-sound-mark[data-burst]::before {animation:ui-sound-mark-ring 880ms 140ms cubic-bezier(.2,.7,.3,1) both}
.ui-sound-mark[data-burst]::after {animation:ui-sound-mark-ring 880ms 360ms cubic-bezier(.2,.7,.3,1) both}
.ui-sound-mark[data-burst] svg path {transform-box:fill-box;transform-origin:center;animation:ui-sound-mark-bar 300ms 300ms ease-in-out 4 alternate both}
.ui-sound-mark[data-burst] svg path:nth-child(2n) {animation-delay:380ms}
.ui-sound-mark[data-burst] svg path:nth-child(3n) {animation-delay:450ms}
@keyframes ui-sound-mark-pop {0% {transform:scale(.2) rotate(-30deg);opacity:0} 55% {transform:scale(1.24) rotate(6deg);opacity:1} 100% {transform:scale(1) rotate(0);opacity:1}}
@keyframes ui-sound-mark-ring {0% {transform:scale(1);opacity:.95} 100% {transform:scale(2.7);opacity:0}}
@keyframes ui-sound-mark-bar {from {transform:scaleY(.4)} to {transform:scaleY(1.3)}}

/* Toast: one line of good news that needs no answer (a mood unlocked). The page places
   the host; the toast slides in from above, stays about four seconds and can be tapped
   away. One at a time; the next waits for it. The surface it sits on can remap
   --ui-toast-* (the gacha stage does). */
.ui-toast-host {display:grid;justify-items:center;pointer-events:none}
.ui-toast {pointer-events:auto;display:flex;align-items:center;gap:12px;max-width:100%;min-height:54px;margin:0;padding:10px 18px 10px 11px;border:1px solid var(--ui-toast-border,var(--ui-border));border-radius:19px;background:var(--ui-toast-surface,var(--ui-sheet));color:var(--ui-toast-ink,var(--ui-text));box-shadow:0 14px 36px var(--ui-toast-shadow,var(--ui-shadow-strong));font:inherit;text-align:left;cursor:pointer;animation:ui-toast-in 420ms cubic-bezier(.22,1,.36,1) both}
.ui-toast[data-leaving] {animation:ui-toast-out 220ms cubic-bezier(.4,0,1,1) both}
.ui-toast-icon {display:grid;place-items:center;flex:none;width:34px;height:34px;border-radius:50%;background:var(--ui-toast-accent,var(--ui-action));color:var(--ui-toast-accent-ink,var(--ui-action-ink))}
.ui-toast-icon svg {display:block;width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.ui-toast-text {min-width:0}
.ui-toast strong {display:block;font-size:14px;font-weight:750;line-height:1.3}
.ui-toast small {display:block;font-size:12px;line-height:1.4;color:var(--ui-toast-muted,var(--ui-muted))}
/* One small action at the end of a toast; the text shrinks first, the button never wraps. */
.ui-toast .ui-toast-action {flex:none;margin-left:auto;white-space:nowrap}
@keyframes ui-toast-in {from {opacity:0;transform:translateY(-14px) scale(.96)} to {opacity:1;transform:none}}
@keyframes ui-toast-out {to {opacity:0;transform:translateY(-8px)}}
/* The same toast rising from below, for a host placed near the bottom. */
@keyframes ui-toast-in-up {from {opacity:0;transform:translateY(14px) scale(.96)} to {opacity:1;transform:none}}
@keyframes ui-toast-out-down {to {opacity:0;transform:translateY(8px)}}
@media(prefers-reduced-motion:reduce) {
 .ui-toast,.ui-toast[data-leaving] {animation-duration:1ms}
 .ui-sound-mark[data-burst],.ui-sound-mark[data-burst]::before,.ui-sound-mark[data-burst]::after,.ui-sound-mark[data-burst] svg path {animation:none}
}
@media(forced-colors:active) {
 .ui-toast {background:Canvas;color:CanvasText;border:1px solid CanvasText;box-shadow:none}
 .ui-toast-icon,.ui-sound-mark[data-tone=new] {background:Highlight;color:HighlightText;box-shadow:none}
 .ui-sound-mark {background:Canvas;color:CanvasText;box-shadow:0 0 0 1px CanvasText}
 .ui-sound-mark::before,.ui-sound-mark::after {border-color:Highlight}
}
