@import url("https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@400&family=Geist:wght@300;400;500;600&family=Geist+Mono:wght@500;600&display=swap");

/* Bridge components. Every value comes from tokens.css. Motion values live here as custom
   properties because the token file has no motion family. */
:root {
  --dur-press: 90ms;
  --dur-move: 150ms;
  --dur-panel: 230ms;
  --dur-exit: 170ms;
  --dur-wallpaper: 900ms;
  --dur-close: 110ms;   /* menus and toasts closing */
  --dur-ink: 200ms;    /* a glass panel changing shade, or its content switching between white and black (Readability): one quick, smooth fade */
  --dur-marquee: 1500ms; /* a now-playing title that doesn't fit runs past once on hover */
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-enter: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
  --ease-spring: cubic-bezier(0.34, 1.32, 0.64, 1);   /* a soft spring: grows a touch past, then settles (selection, covers) */
  --select-grow: 1.04;
  --tile-grow: 1.08;
  /* Tile shadows are sized to fit the scroll gutters below, so they are never clipped. */
  --shadow-tile: 0 4px 12px rgba(0, 0, 0, 0.30);
  --shadow-lift: 0 4px 12px rgba(0, 0, 0, 0.20), 0 1px 3px rgba(0, 0, 0, 0.10);   /* fits a list's gutter (see .b-scroll) */
  /* Selected, everywhere (top bar tabs, switches, rows, chips, settings rows, Files): a neutral lighter pane with the accent's
     light glowing inside its edge, a rim in the accent's light tone, and a lift shadow with a faint accent halo (F1's
     pane with HUX's inner glow). */
  --selected: rgba(255, 255, 255, 0.10);
  /* Neon: the edge is a lit tube (a near-white lavender core with saturated violet just inside and
     outside it, bleeding a little each way) over the same wide inner glow. The outer part fits an 8px gutter. */
  --selected-edge: inset 0 0 0 1px rgba(var(--accent-light-rgb), 0.95), inset 0 0 0 2px rgba(var(--accent-rgb), 0.55), inset 0 0 6px rgba(var(--accent-rgb), 0.75),
    inset 0 0 26px rgba(var(--accent-rgb), 0.95), 0 0 0 1px rgba(var(--accent-rgb), 0.45), 0 0 6px rgba(var(--accent-rgb), 0.55), 0 2px 6px rgba(0, 0, 0, 0.16);
  /* Highlighted (decision 146): where the pointer, the keyboard or the D-pad is. The same neon edge (the lit core line
     and the violet just outside it, bleeding a little outward) with no glow inside: the inner glow means selected. */
  --highlight-edge: inset 0 0 0 1px rgba(var(--accent-light-rgb), 0.95), 0 0 0 1px rgba(var(--accent-rgb), 0.45), 0 0 6px rgba(var(--accent-rgb), 0.55);
  /* The same edge in two parts, for a part that has a border of its own (a search bar): the core line is its border, the
     glow sits just outside it, so there's no gap between them (decision 152). */
  --highlight-line: rgba(var(--accent-light-rgb), 0.95);
  --highlight-glow: 0 0 0 1px rgba(var(--accent-rgb), 0.45), 0 0 6px rgba(var(--accent-rgb), 0.55);
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body { background: var(--wall-base); color: var(--ink); font-family: var(--font-text); font-size: 14px; line-height: 20px; -webkit-font-smoothing: antialiased; }
/* Highlighted, on anything that can be chosen (decision 149): under the pointer or with the keyboard's focus it gets
   the highlight edge alone (no fill, no glow inside; decision 151), the same as the D-pad's highlight (.is-pad-focus). What's selected,
   open, switched on or the current page keeps its own look. Kept light (two classes' weight) and early, so a part's own
   hover (buttons, tiles, covers) still wins and only parts with none get this. */
:where(button, a[href], summary, [role=button], [role=tab], [role=option], [role=switch], [role=radio], [role=menuitem], [role=menuitemradio], [role=menuitemcheckbox], [data-click]):not(.is-selected, .is-open, [aria-selected="true"], [aria-checked="true"], [aria-current="page"], [disabled], .primary):is(:hover, :focus-visible) {
  box-shadow: var(--highlight-edge); }

/* A stand-in live wallpaper for previews: the app draws real wallpapers. */
.b-wall {
  position: relative; min-height: 100%; padding: var(--space-5);
  background:
    radial-gradient(60% 80% at 15% 20%, color-mix(in srgb, var(--accent) 55%, transparent), transparent 70%),
    radial-gradient(55% 75% at 85% 75%, color-mix(in srgb, var(--accent-2) 70%, transparent), transparent 70%),
    radial-gradient(40% 50% at 60% 10%, rgba(255, 170, 120, 0.25), transparent 70%),
    var(--wall-base);
}
.b-wall.busy::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(115deg, rgba(255,255,255,0.10) 0 2px, transparent 2px 18px); }
.b-wall > * { position: relative; z-index: 1; }
.b-row { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.b-col { display: flex; flex-direction: column; gap: var(--space-2); }

/* <small> is 12px everywhere (the browser's own "smaller" lands between sizes on the type scale). */
.b-app small { font-size: 12px; }

/* THE glass. One look for every surface. */
.b-glass {
  background: var(--glass);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--blur-glass-saturate));
  backdrop-filter: blur(var(--blur-glass)) saturate(var(--blur-glass-saturate));
  border: 1px solid var(--glass-edge);
  box-shadow: var(--shadow-edge-light), var(--shadow-glass);
  border-radius: var(--radius);
}
.b-inset { background: var(--glass-inset); border-radius: var(--radius); }

/* Labels */
.b-label { font-family: var(--font-display); font-size: 11px; line-height: 16px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--ink-muted); }
.b-muted { color: var(--ink-muted); }
.b-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 500; }

/* Buttons */
.b-btn {
  height: var(--size-control); padding: 0 var(--space-4); display: inline-flex; align-items: center; gap: var(--space-2);
  border-radius: var(--radius); border: 0;   /* the edge is the inset line below: a border left a gap between it and a highlight's edge (a double outline) */
  background: var(--glass); -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--blur-glass-saturate)); backdrop-filter: blur(var(--blur-glass)) saturate(var(--blur-glass-saturate));
  box-shadow: inset 0 0 0 1px var(--glass-edge), var(--shadow-edge-light);
  color: var(--ink); font: 600 14px/20px var(--font-text); cursor: pointer;
  transition: transform var(--dur-press) var(--ease-standard), background-color var(--dur-press) var(--ease-standard);
}
.b-btn:hover, .b-btn.is-focus, .b-btn.is-pad-focus { background-color: color-mix(in srgb, var(--glass) 100%, transparent); box-shadow: var(--highlight-edge); }
.b-btn:active, .b-btn.is-pressed { transform: scale(0.97); box-shadow: var(--shadow-edge-light), inset 0 0 0 999px var(--glass-lift-strong); }
.b-btn.primary { background: var(--accent); color: var(--on-accent); border-color: transparent;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.32); }
/* Icons on an accent button always use the button's own text colour, even inside rows or menus that tint icons. */
.b-btn.primary .b-icon, .b-item .b-btn.primary .b-icon { color: var(--on-accent); }
.b-btn.console { height: var(--size-control-lg); padding: 0 var(--space-6); font: 600 18px/20px var(--font-display); }
/* Play (the big accent button) gives off a soft glow in its own colour. */
.b-btn.primary.console { box-shadow: 0 0 22px color-mix(in srgb, var(--accent) 45%, transparent), 0 6px 20px color-mix(in srgb, var(--accent-2) 30%, transparent); }
.b-btn.quiet { background: transparent; border-color: transparent; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
.b-btn.quiet:hover, .b-btn.quiet.is-focus, .b-btn.quiet.is-pad-focus { box-shadow: var(--highlight-edge); }
.b-btn.danger { color: var(--danger); }
/* A menu row that destroys something (Remove web app): the danger colour for its icon and words. */
.b-item.danger { color: var(--danger); }
.b-btn.sm { height: var(--size-control-sm); padding: 0 var(--space-3); border-radius: var(--radius); font-size: 13px; }
/* Disabled looks disabled and never reacts: no hover light, no press, half strength (primary buttons included). */
.b-btn[disabled] { color: var(--ink-muted); cursor: default; opacity: 0.55; pointer-events: none; box-shadow: inset 0 0 0 1px var(--glass-edge), var(--shadow-edge-light); }   /* still readable: you can see what it is */
.b-btn.primary[disabled] { color: var(--on-accent); }
.b-btn.quiet[disabled] { box-shadow: none; }   /* a quiet button has no edge, disabled or not (Files' Forward) */
.b-field:has(input:disabled) { opacity: 0.5; }
.b-icon-btn { width: var(--size-control); padding: 0; justify-content: center; }
/* Standard buttons: text always centred, and no text button narrower than 96px, so short labels never make odd little buttons. */
.b-btn { justify-content: center; }
.b-btn:not(.b-icon-btn) { min-width: 96px; }
/* A group of actions is a grid of equal-width buttons, never a ragged row sized by label length (as in Apple's panels).
   Two columns by default; .wide spans the full row (put the main action first and wide). */
.b-actions { display: grid; grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr)); gap: var(--space-2); }
.b-actions > .wide { grid-column: 1 / -1; }
.b-actions > .b-btn { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Dialog buttons are all the same width too. */
.b-icon-btn.sm { width: var(--size-control-sm); }
.b-icon { width: var(--size-icon); height: var(--size-icon); stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* Fields */
.b-field {
  height: var(--size-control); display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-3);
  border-radius: var(--radius); background: var(--glass-inset); border: 1px solid var(--glass-edge); color: var(--ink);
}
.b-field.on-wall { background: var(--glass); -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--blur-glass-saturate)); backdrop-filter: blur(var(--blur-glass)) saturate(var(--blur-glass-saturate)); box-shadow: var(--shadow-edge-light), var(--shadow-glass); }
.b-field.hero { height: var(--size-hero-search); padding: 0 var(--space-4); font-size: 18px; }
.b-field input { flex: 1; min-width: 0; background: none; border: 0; outline: 0; color: var(--ink); font: inherit; }
/* A search bar (any field) is highlighted as a whole, around its edge, never the text box inside it (decision 152):
   under the pointer, or when the D-pad is on it. */
.b-field input.is-pad-focus { background: none !important; box-shadow: none !important; }
.b-field input::placeholder { color: var(--ink); opacity: 0.9; }   /* white, like the rest of the bar's text */
/* No Windows UI in fields: Edge's own password reveal and clear buttons are hidden (Bridge's eye and × take their place). */
.b-app input::-ms-reveal, .b-app input::-ms-clear { display: none; }
.b-field .b-field-clear.is-open { color: var(--accent); }
.b-field .b-icon { color: var(--ink-muted); }

/* Chips and segmented switch */
.b-chip { height: var(--size-control-sm); padding: 0 var(--space-3); display: inline-flex; align-items: center; gap: var(--space-1);
  border-radius: var(--radius); background: var(--glass-inset); color: var(--ink-muted); font: 600 13px/18px var(--font-text); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
  transition: transform var(--dur-move) var(--ease-standard), background-color var(--dur-move) var(--ease-standard), color var(--dur-move) var(--ease-standard); }
.b-chip.is-selected { color: var(--ink); background: var(--selected); box-shadow: var(--selected-edge); transform: scale(var(--select-grow)); }
/* Segmented switch: the selected option fills the housing edge to edge (same 16px corners, no inset) in the
   --selected switch highlight. In the app it is one highlight that slides between options (150ms, standard curve), the way the
   Electron Bridge's tabs, Settings list and Games filters did. */
/* Every switch housing has the same glassy edge as a search field: a 1px glass edge and the top light. */
.b-seg.b-inset { border: 1px solid var(--glass-edge); box-shadow: var(--shadow-edge-light); }
/* Every option in a switch is the same width (as wide as the longest label), so the highlight is one size as it slides. */
.b-seg { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; padding: 0; gap: 0; border-radius: var(--radius); }
.b-seg > span { height: 38px; padding: 0 var(--space-4); display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius);
  font: 500 13px/18px var(--font-display); color: var(--ink-muted);
  transition: background-color var(--dur-move) var(--ease-standard), color var(--dur-move) var(--ease-standard); }
.b-seg > span.is-selected { color: var(--ink); background: var(--selected); box-shadow: var(--selected-edge); }

/* Toggle */
/* A switch (decision 148): its edge is an inset line, not a border, so the on look's neon edge has no gap in it. On, it
   looks like a slider's fill: the selected look (the neon edge with the glow inside) with the slider's white knob. */
.b-toggle { width: 46px; height: 28px; border-radius: var(--radius-round); background: var(--glass-inset); border: 0; box-shadow: inset 0 0 0 1px var(--glass-edge); position: relative; flex: none;
  transition: background-color var(--dur-move) var(--ease-standard), box-shadow var(--dur-move) var(--ease-standard); }
.b-toggle::after { content: ""; position: absolute; top: 4px; left: 4px; width: 20px; height: 20px; border-radius: var(--radius-round); background: var(--ink-muted); transition: transform var(--dur-move) var(--ease-standard), background-color var(--dur-move) var(--ease-standard); }
.b-toggle.on { background: var(--selected); box-shadow: var(--selected-edge); }
.b-toggle.on::after { transform: translateX(18px); background: #ffffff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.30), 0 0 0 0.5px rgba(0, 0, 0, 0.10); }   /* the slider thumb's white and shadow */

/* Slider and progress */
.b-track { height: 6px; border-radius: var(--radius-round); background: var(--glass-inset); position: relative; flex: 1 1 auto; align-self: center; min-width: 40px; }
.b-col > .b-track, .b-track.bar { flex: none; height: 4px; align-self: stretch; }
.b-track > i { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: var(--accent); }
/* A slider's filled part wears the selected look (FIXES #108), like a selected tab: the accent-tinted glass with its
   thin accent edge, not a solid colour. The track is a little taller so the edge shows. Thin bars (progress, levels)
   keep the solid fill. */
.b-track[role="slider"] { height: 10px; }
.b-track[role="slider"] > i { background: var(--selected); box-shadow: var(--selected-edge); min-width: 10px; }
.b-track > b { position: absolute; top: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px; border-radius: var(--radius-round); background: #ffffff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.30), 0 0 0 0.5px rgba(0, 0, 0, 0.10); }

/* Top bar */
.b-topbar { height: var(--size-control-lg); display: grid; grid-template-columns: 1fr auto 1fr; column-gap: var(--space-4); align-items: center; padding: 0 var(--space-2); }   /* the gap: a wide now playing never touches the tabs */
.b-topbar .left, .b-topbar .right { display: flex; align-items: center; gap: var(--space-1); }
.b-topbar .right { justify-content: flex-end; }
/* Top bar tabs are all the same width (as wide as the longest tab name), like switch options. */
.b-tabs { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--space-1); }
.b-tab { height: 36px; padding: 0 var(--space-4); display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius);
  font: 500 14px/20px var(--font-display); color: var(--ink); text-decoration: none;   /* white in the top bar, selected or not */
  transition: transform var(--dur-move) var(--ease-standard), color var(--dur-move) var(--ease-standard), background-color var(--dur-move) var(--ease-standard); }
.b-tab:hover { color: var(--ink); box-shadow: var(--highlight-edge); }
.b-tab.is-selected { color: var(--ink); background: var(--selected); box-shadow: var(--selected-edge); transform: scale(var(--select-grow)); }
.b-status { height: 36px; padding: 0 var(--space-2); display: inline-flex; align-items: center; gap: var(--space-2); border-radius: var(--radius); color: var(--ink); }
.b-status:hover { box-shadow: var(--highlight-edge); }
.b-logo { height: 36px; padding: 0 var(--space-3) 0 var(--space-2); display: inline-flex; align-items: center; gap: var(--space-2); border-radius: var(--radius); color: var(--ink); text-decoration: none; font: 400 16px/20px var(--font-brand); letter-spacing: 1.6px; text-transform: uppercase; }
/* The mark is the accent, with a soft shadow to stand out; on Home (the logo selected, on the accent tint) it
   turns white so it still shows. */
.b-logo svg { width: 30px; height: 21px; flex: none; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.45)); }
.b-logo.is-selected { --logo: #ffffff; }
.b-logo:hover { box-shadow: var(--highlight-edge); }
.b-logo.is-selected { background: var(--selected); box-shadow: var(--selected-edge); transform: scale(var(--select-grow)); }
a { color: inherit; }

/* Menus, list rows */
.b-menu { padding: var(--space-2); min-width: 220px; display: flex; flex-direction: column; gap: 2px; box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.b-item { flex: none; height: var(--size-control); padding: 0 var(--space-3); display: flex; align-items: center; gap: var(--space-3); border-radius: var(--radius); color: var(--ink);
  transition: transform var(--dur-move) var(--ease-standard), background-color var(--dur-move) var(--ease-standard); }
.b-item .b-icon { color: var(--ink-muted); }
.b-item .end { margin-left: auto; color: var(--ink-muted); }
.b-item.is-focus { box-shadow: var(--highlight-edge); }
/* Selected rows look exactly like the top bar's selected tab: the accent-tinted glass with its thin accent edge
   (one selected look everywhere, no solid fill). A highlighted row has the edge alone: no fill, no glow inside. */
.b-item.is-selected { background: var(--selected); box-shadow: var(--selected-edge); transform: scale(1.02); }
.b-divider { height: 1px; margin: var(--space-1) var(--space-2); background: var(--glass-edge); }

/* Toast */
/* Every bottom popup (toasts, undo, the Files selection bar) is one size: 560 x 52, centred 24px above the bottom. */
.b-toast { width: 560px; max-width: calc(100% - 32px); height: 52px; flex: none; padding: 0 var(--space-2) 0 var(--space-4); display: flex; align-items: center; gap: var(--space-3); box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.b-toast .dot { width: 8px; height: 8px; border-radius: var(--radius-round); flex: none; }

/* Tiles: game covers, wallpapers, Overview cards */
.b-tile { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-tile); flex: none;
  transition: transform var(--dur-move) var(--ease-standard), box-shadow var(--dur-move) var(--ease-standard); }
/* Pointing at a tile with the mouse is the same as moving the highlight to it: it grows in place. */
.b-tile.is-selected { transform: scale(var(--tile-grow)); box-shadow: var(--shadow-lift); }
.b-tile:hover, .b-tile.is-hover { transform: scale(var(--tile-grow)); box-shadow: var(--highlight-edge), var(--shadow-lift); }
/* Grid covers: on mouse hover only (a controller just moves the highlight as usual: A plays, Y opens the menu), Play, Details and Favorite fade up over the bottom of the cover and the name rises above them. */
.b-cover .hover-actions { position: absolute; left: 10px; right: 10px; bottom: 10px; display: flex; gap: 6px; opacity: 0; transform: translateY(6px);
  transition: opacity var(--dur-move) var(--ease-standard), transform var(--dur-move) var(--ease-standard); }
.b-cover .hover-actions .b-btn { width: 36px; height: 36px; }
.b-cover .hover-actions .b-btn.primary { flex: 1; }
.b-cover:has(.hover-actions)::after { content: ""; position: absolute; inset: 40% 0 0 0; border-radius: inherit; pointer-events: none; opacity: 0;
  background: linear-gradient(180deg, transparent, rgba(5, 7, 12, 0.75)); transition: opacity var(--dur-move) var(--ease-standard); }
.b-cover:has(.hover-actions) > span:not(.b-badge) { transition: transform var(--dur-move) var(--ease-standard); z-index: 1; }
.b-cover.is-hover .hover-actions, .b-cover:hover .hover-actions { opacity: 1; transform: none; z-index: 2; }
.b-cover.is-hover:has(.hover-actions)::after, .b-cover:hover:has(.hover-actions)::after { opacity: 1; }
.b-cover.is-hover:has(.hover-actions) > span:not(.b-badge), .b-cover:hover:has(.hover-actions) > span:not(.b-badge) { transform: translateY(-46px); }
.b-cover { width: 132px; aspect-ratio: 2 / 3; }
.b-cover.lg { width: 250px; }
/* On the Games row, covers grow from their left edge so the selected cover stays on the same left line as the hero title,
   Play button and the Recent / Favorites / A–Z bar. The 28px gap leaves room for the 20px it grows to the right. */
.b-cover.lg { transform-origin: left center; }
.b-cover > .art { position: absolute; inset: 0; border-radius: inherit; }
/* The selected game's hero becomes part of the wallpaper behind the whole Games page. Heroes are wide and short
   (Steam's are 3840 x 1240), so the hero spans the full width at the top at its own shape, never cropped or stretched,
   and a mirror image of it continues straight down underneath, so there's never an edge where the hero ends. The whole
   backdrop then fades softly into the wallpaper across the bottom half of the screen. Covers have no reflection. */
.b-backdrop { position: absolute !important; inset: 0; z-index: 0 !important; pointer-events: none; transition: opacity var(--dur-panel) var(--ease-standard);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 40%, rgba(0, 0, 0, 0.55) 62%, transparent 92%); mask-image: linear-gradient(180deg, #000 0%, #000 40%, rgba(0, 0, 0, 0.55) 62%, transparent 92%); }
.b-backdrop > .hero { width: 100%; aspect-ratio: 3840 / 1240; background-size: cover; background-position: center; -webkit-box-reflect: below 0; }
.b-backdrop::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(5, 7, 12, 0.70) 0%, rgba(5, 7, 12, 0.30) 40%, transparent 70%), linear-gradient(180deg, transparent 45%, rgba(5, 7, 12, 0.35) 100%); }

/* Now playing: compact */
.b-np { height: 40px; display: inline-flex; align-items: center; gap: 10px; padding: 0 4px 0 5px; border-radius: var(--radius); background: var(--glass-inset); border: 1px solid var(--glass-edge); box-shadow: var(--shadow-edge-light); }
.b-np .art { width: 30px; height: 30px; border-radius: 50%; flex: none; background: #3a3f6b center / cover; box-shadow: inset 0 0 0 1px rgba(255,255,255,.14); }
/* The album art is round: the real cover, cropped to a circle (stand-in here). */
.b-np .meta { display: flex; flex-direction: column; gap: 1px; max-width: 150px; margin-right: 4px; }
.b-np .meta b { font-size: 13px; line-height: 16px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.b-np .meta span { font-size: 12px; line-height: 15px; color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.b-np .b-btn { width: 30px; height: 30px; padding: 0; justify-content: center; }
.b-np .b-btn + .b-btn { margin-left: -6px; }
.b-np .b-icon { width: 16px; height: 16px; }

/* Scrollbar: the ONE scrollbar for every scroll area in Bridge (and injected into web pages). Every scroller on a Bridge
   page gets it, .b-scroll or not, so the system's arrowed scrollbar never shows.
   6px glass pill at rest, 10px on hover or drag, no arrows, invisible track, 4px in from the edge. */
.b-scroll { overflow-x: hidden; overflow-y: auto; padding-inline: 4px; }
.b-scroll.h { overflow-x: auto; overflow-y: hidden; padding-inline: 0; padding-block: 8px; }
/* Shadows are never cut off. A scroll area clips whatever leaves its box, so every scroll area that holds tiles or
   lifted items gets a gutter as deep as the float shadow reaches, cancelled by an equal negative margin: the content
   still lines up exactly where it would, but a grown tile and its shadow (and a dragged item) have room to show.
   Gutters are 32px (24px inside a panel or dialog, 32px below) and tile shadows (--shadow-tile, --shadow-lift when grown)
   reach less than that, so no shadow is ever clipped by any container. */
.b-scroll.tiles { padding: 32px 32px 40px; margin: -32px -32px -40px; }
.b-scroll.tiles.h { padding: 32px 32px 44px; margin: -32px -32px -16px; }
.b-scroll.tiles-in { padding: 12px 24px 24px; margin: -8px -24px 0; }
/* Never set scrollbar-width or scrollbar-color for Chromium/WebView2: either one makes it ignore the rules below and draw native arrows. */
@supports not selector(::-webkit-scrollbar) { .b-scroll { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.28) transparent; } }
.b-scroll::-webkit-scrollbar, .b-app *::-webkit-scrollbar { width: 14px; height: 14px; }
.b-scroll::-webkit-scrollbar-track, .b-app *::-webkit-scrollbar-track { background: transparent; margin: 12px; }
.b-scroll::-webkit-scrollbar-corner, .b-app *::-webkit-scrollbar-corner { background: transparent; }
.b-scroll::-webkit-scrollbar-button, .b-app *::-webkit-scrollbar-button { display: none; height: 0; width: 0; }
.b-scroll::-webkit-scrollbar-thumb, .b-app *::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.28); border-radius: var(--radius-round); border: 4px solid transparent; background-clip: padding-box; min-height: 40px; }
.b-scroll::-webkit-scrollbar-thumb:hover, .b-app *::-webkit-scrollbar-thumb:hover { border-width: 2px; background-color: rgba(255, 255, 255, 0.40); }
.b-scroll::-webkit-scrollbar-thumb:active, .b-app *::-webkit-scrollbar-thumb:active { border-width: 2px; background-color: rgba(255, 255, 255, 0.50); }
/* Shown only when it's of use (FIXES #77): the thumb appears while the pointer is over its scroller or it's scrolling
   (.is-scrolling, set for a second by any scroll: wheel, keys, controller), and is invisible the rest of the time. */
.b-app *:not(:hover):not(.is-scrolling)::-webkit-scrollbar-thumb { background-color: transparent; }
/* Quiet: for a grid that should sit centred in its frame (an app drawer). The scrollbar's room is kept on both sides,
   so the content is centred whether or not there is anything to scroll, and the thumb shows only while it is
   scrolling, not on hover. */
.b-scroll.quiet { scrollbar-gutter: stable both-edges; padding-inline: 0; }
.b-app .b-scroll.quiet:not(.is-scrolling)::-webkit-scrollbar-thumb, .b-scroll.quiet:not(.is-scrolling)::-webkit-scrollbar-thumb { background-color: transparent; }

/* Panels that sit beside a page: sidebars, details panels, flyout panels */
.b-panel { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); min-height: 0; }
.b-side { width: 280px; flex: none; }

/* A web page, web app or Quick Look picture: content Bridge never restyles, in a 16px rounded frame */
.b-frame { border-radius: var(--radius); overflow: hidden; background: #ffffff; color: #1d2433; box-shadow: var(--shadow-glass); min-width: 0; min-height: 0; }

/* Web view: the glass panel that marks where the page goes. With a page showing, the page fills the panel exactly
   (same box, same 16px corners) and covers it. With no page (new tab, loading, private new tab, error and certificate
   pages) the panel's glass shows, so you always see where the page lives. Nothing white ever flashes. */
.b-view { flex: 1; min-width: 0; min-height: 0; display: flex; gap: var(--space-2); padding: var(--space-2); position: relative; }
.b-view:has(> .b-frame) { padding: 0; gap: 0; border-color: transparent; background: transparent; box-shadow: var(--shadow-glass); border-radius: var(--radius); }   /* rounded like the page, so its shadow's corners never show past the page's */
.b-view > .b-frame { flex: 1; box-shadow: none; }
.b-view.inside { flex-direction: column; align-items: center; justify-content: center; padding: var(--space-5); gap: var(--space-4); }
.b-load { position: absolute; top: 3px; left: var(--space-5); right: var(--space-5); height: 2px; border-radius: var(--radius-round); overflow: hidden; z-index: 1; }
.b-load > i { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: var(--accent); }

/* Settings row: label left, control right, optional one-line description */
.b-srow { min-height: 56px; padding: var(--space-2) var(--space-4); display: flex; align-items: center; gap: var(--space-4); border-radius: var(--radius); }
/* Rows never light up on hover: only their control is clickable (rules: only what you can act on as a whole highlights). */
.b-srow .txt { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.b-srow .txt span { font-size: 12px; line-height: 16px; color: var(--ink-muted); }

/* Dialogs: one glass over a scrim, centred, title + body + buttons right */
.b-scrim { position: absolute; inset: 0; background: var(--scrim); }
.b-dialog { width: 440px; padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.b-dialog .actions { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--space-2); }
.b-dialog .actions > .b-btn { min-width: 0; white-space: nowrap; }

/* Badges and keys */
.b-badge { height: 20px; padding: 0 8px; display: inline-flex; align-items: center; border-radius: var(--radius); background: var(--glass-lift-strong); color: var(--ink); font: 600 11px/16px var(--font-text); }
.b-badge.accent { background: var(--accent); color: var(--on-accent); }
/* Update ready: lit like a selected item (the neon edge), so it's easy to see on a cover. */
.b-badge.update { background: var(--selected); box-shadow: var(--selected-edge); color: var(--ink); }
.b-kbd { min-width: 22px; height: 22px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius); background: var(--glass-inset); border: 1px solid var(--glass-edge); font: 500 11px/16px var(--font-mono); color: var(--ink-muted); }

/* Spinner: the one busy indicator */
.b-spin { width: 16px; height: 16px; border-radius: var(--radius-round); border: 2px solid var(--glass-lift-strong); border-top-color: var(--ink); flex: none; }

/* One glass everywhere, even over a web page, a web app or a game: it always shows what's behind it, blurred. Over
   bright content (the app reads the brightness behind each panel; see Readability) the same glass turns light, like
   Flowdesk: a see-through white with a white rim and a fine dark hairline, soft blue-grey shadows, black text, white
   fields, and a white selected pill with the violet glow inside it. A light wallpaper gets this too. Mockups mark
   that state with .on-bright. */
.on-bright, .on-bright .b-glass {
  --glass: rgba(255, 255, 255, 0.30);
  --ink: #121318; --ink-muted: #474c58; --ink-faint: #666b78;
  --glass-lift: rgba(255, 255, 255, 0.50); --glass-lift-strong: rgba(255, 255, 255, 0.70); --glass-inset: rgba(255, 255, 255, 0.60); --glass-edge: rgba(20, 24, 45, 0.12);
  --shadow-edge-light: inset 0 1px 0 #ffffff, 0 0 0 0.5px rgba(20, 24, 45, 0.16);
  --shadow-glass: 0 10px 22px rgba(40, 45, 90, 0.13), 0 3px 8px rgba(40, 45, 90, 0.07), 0 1px 2px rgba(40, 45, 90, 0.06);
  --shadow-float: 0 12px 24px rgba(40, 45, 90, 0.16), 0 4px 10px rgba(40, 45, 90, 0.08), 0 1px 3px rgba(40, 45, 90, 0.06);
  --shadow-lift: 0 4px 12px rgba(40, 45, 90, 0.12), 0 1px 3px rgba(40, 45, 90, 0.06);
  /* Status colours deep enough to read on light glass (the light ones are made for dark glass). */
  --danger: #b4232c; --success: #12784a; --warning: #9a5a00;
  /* Selected: a white pill with the violet glow inside its edge. */
  --selected: rgba(255, 255, 255, 0.88);
  --selected-edge: inset 0 0 0 1px rgba(var(--accent-rgb), 0.85), inset 0 0 0 2px rgba(var(--accent-rgb), 0.25), inset 0 0 5px rgba(var(--accent-rgb), 0.30),
    inset 0 0 24px rgba(var(--accent-rgb), 0.48), 0 2px 6px rgba(0, 0, 0, 0.14);   /* light: the glow is inside only */
  --highlight-edge: inset 0 0 0 1px rgba(var(--accent-rgb), 0.85), 0 0 0 1px rgba(var(--accent-rgb), 0.25), 0 0 6px rgba(var(--accent-rgb), 0.30);   /* light: the edge, no glow inside */
  --highlight-line: rgba(var(--accent-rgb), 0.85);
  --highlight-glow: 0 0 0 1px rgba(var(--accent-rgb), 0.25), 0 0 6px rgba(var(--accent-rgb), 0.30);
  color: var(--ink); /* text that sets no colour of its own inherits the computed light ink otherwise */
}
/* Selected text: the accent behind it with white text, in both modes (black on blue read badly). */
::selection { background: color-mix(in srgb, var(--accent) 85%, #000000); color: #ffffff; }
/* The wallpaper layer also covers the 1px border, so a bright page never shows through the edge; the edge is drawn on it instead. */
.b-frame { position: relative; }

/* The same scrollbar injected into web pages and web apps: identical shape and behaviour, a neutral grey thumb
   that reads on both light and dark sites. */
.b-scroll.page::-webkit-scrollbar-thumb { background-color: rgba(120, 128, 140, 0.55); }
.b-scroll.page::-webkit-scrollbar-thumb:hover, .b-scroll.page::-webkit-scrollbar-thumb:active { background-color: rgba(120, 128, 140, 0.8); }

/* Glass inside glass: buttons and fields inside any glass surface drop their own blur and use the inset fill. */
.b-glass .b-btn:not(.primary):not(.quiet) { background: var(--glass-inset); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none; }
/* A field inside glass is an outlined pill (F1's search): no fill of its own, a clear edge. On light glass it's a white well. */
.b-glass .b-field { background: transparent; border-color: rgba(255, 255, 255, 0.26); border-radius: var(--radius-round); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none; }
/* A glass field inside a glass panel (the new-tab search) looks exactly like one on the wallpaper (Home's): the panel's
   glass already shows behind it once, so it adds no tint or blur of its own, only its edge, edge light and shadow. */
.b-glass .b-field.on-wall { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: var(--shadow-edge-light), var(--shadow-glass); }
.b-glass .b-btn:not(.primary):not(.quiet):hover, .b-glass .b-btn.is-focus:not(.primary):not(.quiet), .b-glass .b-btn.is-pad-focus:not(.primary):not(.quiet) { box-shadow: var(--highlight-edge); }

/* Files: everything selected (places, tiles, rows, search results) uses the same tint and accent edge as switches and tabs. */
.b-files .is-selected { background: var(--selected) !important; box-shadow: var(--selected-edge); }
.b-files .b-tile.is-selected { box-shadow: var(--selected-edge), var(--shadow-lift); }

/* Editors (PDF, picture, video): a tool rail on the left, the inspector for the current tool on the right. */
.b-rail { display: flex; flex-direction: column; gap: 4px; padding: 6px; flex: none; }
.b-rail > .b-btn { width: 40px; min-width: 0; }
.b-rail > .b-btn.is-selected { background: var(--selected); box-shadow: var(--selected-edge); color: var(--ink); }
.b-swatch { width: 24px; height: 24px; border-radius: 50%; flex: none; box-shadow: inset 0 0 0 1px rgba(255,255,255,.18); }
.b-swatch.is-selected { box-shadow: 0 0 0 2px var(--glass), 0 0 0 4px var(--accent); }
.b-srow .b-btn:not(.b-icon-btn), .b-item .end .b-btn:not(.b-icon-btn), .b-toast .b-btn { min-width: 112px; }
.b-toast > .dot + span, .b-toast.sel > span:first-child { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.b-toast.sel > .b-btn:not(.b-icon-btn) { min-width: 0; }

/* Start-screen clock: thin numerals made of frosted Bridge glass, with no outline. A blurred, brightened layer (.fill)
   is clipped to the digits by an SVG clipPath, so the wallpaper glows through them; .shade is a soft shadow under them.
   The face is set with --clock-font / --clock-weight (thin and elegant). */
.b-glass-clock { position: relative; width: 680px; height: 230px; --clock-font: "Inter Tight", var(--font-text); --clock-weight: 500; }
.b-glass-clock text { font-family: var(--clock-font); font-weight: var(--clock-weight); font-size: 220px; letter-spacing: -4px; font-variant-numeric: tabular-nums; }
.b-glass-clock > svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.b-glass-clock .fill { position: absolute; inset: 0; clip-path: url(#b-clock-clip); background: rgba(255, 255, 255, 0.34);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(1.8) brightness(1.5); backdrop-filter: blur(var(--blur-glass)) saturate(1.8) brightness(1.5); }
.b-glass-clock .shade text { fill: rgba(0, 0, 0, 0.28); filter: blur(12px); transform: translateY(6px); }
.b-glass-clock .edge { display: none; }

/* The game overlay sits in a frame, not glass: blur can't reach under an exclusive full-screen game. */
.b-hud { background: rgba(10, 12, 20, 0.72); border: 1px solid rgba(255, 255, 255, 0.14); border-radius: var(--radius); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35); }

/* Nothing is ever clipped by its scroller: every list scroller keeps a gutter as wide as a grown row or tile needs
   (a 1.02x row on a 1000px list sticks out 10px), and pulls it back with a matching negative margin so content
   still lines up with headers. Inset wells and web pages size their own padding. */
.b-scroll:not(.page):not(.b-inset):not(.b-panel):not(.b-glass):not(.b-menu):not(.h):not(.tiles):not(.tiles-in) { padding: 8px 14px; margin: -8px -14px; }

/* Selected text is always full-strength ink, including the secondary text. */
.is-selected, .is-selected .b-muted, .is-selected .caption, .is-selected .b-label { color: var(--ink) !important; }
.is-selected .b-muted, .is-selected .caption { opacity: 0.9; }
.is-selected b, .b-item.is-selected > span { font-weight: 600; }

/* Settings sections open and close (a disclosure, like macOS System Settings groups) so every tab fits at a glance.
   The header is a 48px row; the chevron turns and the rows slide open (dur-move, standard curve). */
.b-sgroup { border-radius: var(--radius); }
.b-sgroup > summary { list-style: none; height: 48px; padding: 0 var(--space-4); display: flex; align-items: center; gap: var(--space-3);
  border-radius: var(--radius); cursor: pointer; background: var(--glass-lift); transition: background var(--dur-move) var(--ease-standard); }
.b-sgroup > summary::-webkit-details-marker { display: none; }
.b-sgroup > summary:hover { box-shadow: var(--highlight-edge); }
.b-sgroup > summary .t { flex: 1; font-weight: 600; }
.b-sgroup > summary .b-icon { transition: transform var(--dur-move) var(--ease-standard); color: var(--ink-muted); }
.b-sgroup[open] > summary .b-icon { transform: rotate(180deg); }
.b-sgroup[open] > summary .b-num { display: none; }
.b-sgroup > .rows { display: flex; flex-direction: column; gap: 2px; padding: 6px 0 12px; }

/* Edge pill: when a side panel is on auto-hide (the browser's sidebar on the left, Files' Details on the right), a small
   glass pill sits in the screen-edge gutter, centred top to bottom, so you know a flyout is there. Hover or click it
   (or move the pointer / D-pad to that edge) and the panel slides in; the pill fades out while the panel is open. */
.b-edge-pill { position: absolute; top: 50%; width: 5px; height: 64px; margin-top: -32px; border-radius: var(--radius-round); z-index: 6;
  background: rgba(255, 255, 255, 0.55); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12), 0 2px 8px rgba(0, 0, 0, 0.35);
  transition: width var(--dur-move) var(--ease-standard), height var(--dur-move) var(--ease-standard), opacity var(--dur-move) var(--ease-standard); }
.b-edge-pill.left { left: 5px; } .b-edge-pill.right { right: 5px; }
/* A side panel that hides (Files' and Games' Details, like the browser's sidebar): the invisible strip on the screen's edge opens it too. */
.b-edge-gutter { position: absolute; top: 0; bottom: 0; width: 22px; z-index: 5; }
.b-edge-gutter.right { right: 0; }
.b-autopanel { position: absolute; right: 0; top: 0; bottom: 0; z-index: 5; display: flex; }
.b-autopanel > .b-panel { height: auto; }
.b-edge-pill:hover { width: 6px; height: 80px; margin-top: -40px; background: rgba(255, 255, 255, 0.8); }

/* A toast can carry progress (downloads, copies): a 3px accent line along its bottom edge, inside the rounded corners. */
.b-toast { position: relative; overflow: hidden; }
.b-toast > .progress { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--accent); border-radius: 0 2px 2px 0; transition: width var(--dur-move) linear; }

/* Every notification offers its action (or Show) and Dismiss. Toast buttons are a fixed pair (96px each);
   notification cards keep them small: a right-aligned row of two 28px buttons under the text. */
.b-toast:not(.sel) .b-btn:not(.b-icon-btn) { min-width: 96px; }
.note-acts { display: flex; justify-content: flex-end; gap: 6px; margin-top: 6px; }
.note-acts .b-btn { height: 28px; min-width: 76px; padding: 0 10px; font-size: 12px; }

/* The browser's tab list never grows the current tab: it is marked by its tint alone, so the list stays still. */
.b-side .b-item.is-selected { transform: none; }

/* Bridge's own pages. The app draws the wallpaper and the glass blur behind every page it shows, so the page itself is
   see-through (the body background above is for previews). Put .b-app on the <html> of every Bridge page. */
html.b-app, html.b-app body { height: 100%; background: transparent; overflow: hidden; }

/* The white / black switch fades (Readability): the content colours are registered so they can transition, and every
   panel that can switch fades them together over --dur-ink. The glass itself never changes. */
@property --ink { syntax: "<color>"; inherits: true; initial-value: #f4f6fb; }
@property --ink-muted { syntax: "<color>"; inherits: true; initial-value: #aeb6c7; }
@property --ink-faint { syntax: "<color>"; inherits: true; initial-value: #7c859a; }
@property --glass-lift { syntax: "<color>"; inherits: true; initial-value: transparent; }
@property --glass-lift-strong { syntax: "<color>"; inherits: true; initial-value: transparent; }
@property --glass-inset { syntax: "<color>"; inherits: true; initial-value: transparent; }
@property --glass { syntax: "<color>"; inherits: true; initial-value: transparent; }
@property --glass-edge { syntax: "<color>"; inherits: true; initial-value: transparent; }
.b-glass, .b-field.on-wall {
  transition: --ink var(--dur-ink) var(--ease-standard), --ink-muted var(--dur-ink) var(--ease-standard), --ink-faint var(--dur-ink) var(--ease-standard),
    --glass-lift var(--dur-ink) var(--ease-standard), --glass-lift-strong var(--dur-ink) var(--ease-standard),
    --glass-inset var(--dur-ink) var(--ease-standard), --glass-edge var(--dur-ink) var(--ease-standard), --glass var(--dur-ink) var(--ease-standard);
}

/* Hover equals focus, and nothing ever gets a focus ring: keyboard and controller focus look exactly like the mouse over it. */
:focus-visible { outline: none; }
.b-btn:focus-visible { box-shadow: var(--highlight-edge); }
.b-btn.quiet:focus-visible, .b-glass .b-btn:not(.primary):not(.quiet):focus-visible { box-shadow: var(--highlight-edge); }
.b-tab:focus-visible, .b-status:focus-visible, .b-logo:focus-visible, .b-item:focus-visible, .b-srow:focus-visible { box-shadow: var(--highlight-edge); }
.b-tab:focus-visible { color: var(--ink); }
.b-sgroup > summary:focus-visible { box-shadow: var(--highlight-edge); }
.b-tile:focus-visible { transform: scale(var(--tile-grow)); box-shadow: var(--highlight-edge), var(--shadow-lift); }
.b-chip:focus-visible, .b-toggle:focus-visible, .b-seg > span:focus-visible { box-shadow: var(--highlight-edge); }
.b-seg > span.is-pad-focus { box-shadow: var(--highlight-edge); }

/* The one highlight that slides (switches and top bar tabs). In the app the selected option draws no fill of its own; a
   single .b-slide carries it. At rest it sits in the selected option's own grid cell (column --c), so it lines up with
   the option to the pixel; when the selection changes the app glides it from the old cell to the new one with a
   transform (--dur-move, standard curve). Options are equal width, so it never changes size. Each option sits in its
   own column (the app numbers them) and above the highlight. */
.b-slide { grid-row: 1; grid-column: var(--c); align-self: stretch; border-radius: var(--radius); background: var(--selected); box-shadow: var(--selected-edge);
  pointer-events: none; transition: opacity var(--dur-move) var(--ease-standard); }
.b-tabs > .b-slide { transform: scale(var(--select-grow)); }
.b-slide.none { opacity: 0; }
.b-seg:has(> .b-slide) > span, .b-tabs:has(> .b-slide) > .b-tab { grid-row: 1; position: relative; }
.b-seg:has(> .b-slide) > span.is-selected, .b-tabs:has(> .b-slide) > .b-tab.is-selected { background: none; box-shadow: none; }

/* A selected (or focused) settings row grows and brightens like every other row. */
.b-srow { transition: transform var(--dur-move) var(--ease-standard), background-color var(--dur-move) var(--ease-standard); }
.b-srow.is-selected { background: var(--selected); box-shadow: var(--selected-edge); transform: scale(1.02); }

/* The spinner turns once every --dur-spin, steadily. */
:root { --dur-spin: 800ms; }
@keyframes b-spin { to { transform: rotate(360deg); } }
.b-spin { animation: b-spin var(--dur-spin) linear infinite; }

/* A button whose flyout or menu is open (top-bar status icons, Power) keeps the stronger lift and grows like a
   selected item; the More tab whose menu is open shows the hover lift. */
.b-btn.is-open, .b-btn.quiet.is-open { box-shadow: inset 0 0 0 999px var(--glass-lift-strong); transform: scale(var(--select-grow)); }
.b-tab.is-open { color: var(--ink); background: var(--glass-lift); }
.b-tab .b-icon { width: 14px; height: 14px; }

/* An icon-only switch (Row / Grid on the Games top bar): square 40px options. */
.b-seg.icons > span { width: var(--size-control); padding: 0; }

/* A tab being dragged lifts onto the float shadow and follows the pointer; the rest glide aside to open its gap. */
.b-tab.is-dragging, .b-btn.is-dragging { z-index: 2; box-shadow: var(--shadow-float); background: var(--glass-lift-strong); color: var(--ink); transition: none; }

/* Something waiting (the bell when notifications are unread): a small accent dot at the icon's top right. */
.b-icon-btn.has-dot { position: relative; }
.b-icon-btn.has-dot::after { content: ""; position: absolute; top: 6px; right: 6px; width: 7px; height: 7px; border-radius: var(--radius-round); background: var(--accent);
  box-shadow: 0 0 0 2px var(--glass); }

/* A switch keeps its size wherever it sits (inside a row's end slot it would otherwise lay out as text). */
.b-toggle { display: inline-block; vertical-align: middle; }

/* Calculator (the Calculator flyout, Standard): an inset display with the calculation above the result, a row of
   memory keys, and a four-column keypad of 52px keys (digits on glass, the rest quiet, = in accent). */
.b-calc-display { padding: 12px 14px 10px; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.b-calc-display .expr { min-height: 20px; font-size: 14px; line-height: 20px; font-variant-numeric: tabular-nums; color: var(--ink-muted); white-space: nowrap; }
.b-calc-display output { flex: 1; text-align: right; font-size: 44px; line-height: 52px; font-weight: 600; letter-spacing: -0.5px; font-variant-numeric: tabular-nums;
  white-space: nowrap; transform-origin: right center; }
.b-keypad { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.b-keypad > .b-btn { min-width: 0; height: var(--size-control-lg); padding: 0; font-size: 18px; }
.b-keypad-mem { display: flex; gap: 2px; }
.b-keypad-mem > .b-btn { min-width: 0; flex: 1; padding: 0; }

/* In the app the page is drawn by Bridge under its own interface, so the frame that marks it is see-through. */
.b-frame.hosted { background: transparent; }

/* Fields on bright glass: a near-solid light fill with a hairline edge (a thicker layer on top, like iOS search fields),
   not a darker tint of the panel. */
/* Light content on light glass: the panel's rim is white like the glass's own edge light; fields and keys are white
   wells with a hairline. */
.b-glass.on-bright, .on-bright .b-glass { border-color: rgba(255, 255, 255, 0.85); }
.on-bright .b-field:not(.on-wall), .b-glass.on-bright .b-field:not(.on-wall) { background: rgba(255, 255, 255, 0.88); border-color: rgba(20, 24, 45, 0.10); box-shadow: 0 2px 8px rgba(40, 45, 90, 0.08); }
.on-bright .b-field input::placeholder { color: var(--ink); opacity: 0.9; }
.on-bright .b-kbd, .b-glass.on-bright .b-kbd { background: rgba(255, 255, 255, 0.70); border-color: rgba(20, 20, 40, 0.12); }

/* The pointer works the way you'd expect: the arrow by default, including over words (no text
   cursor over labels and titles); the hand on anything you can click; the text cursor only where you type; resize
   arrows on the resize handles (sidebar width, split view). A row counts as clickable when it has an action (data-click). */
html { cursor: default; }
a[href], button, summary, select, label[for], [role="button"], [role="tab"], [role="link"], [role="switch"], [role="checkbox"],
[role="radio"], [role="menuitemradio"], [role="menuitemcheckbox"], [role="slider"], [role="option"], .b-item[data-click],
.b-btn, .b-icon-btn, .b-tab, .b-logo, .b-chip, .b-seg > span, .b-toggle, .b-track, .b-tile, .b-srow, .b-status,
input[type="checkbox"], input[type="radio"], input[type="range"], input[type="button"], input[type="submit"], input[type="color"], input[type="file"] { cursor: pointer; }
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="button"]):not([type="submit"]):not([type="color"]):not([type="file"]),
textarea, [contenteditable]:not([contenteditable="false"]) { cursor: text; }
[disabled], [aria-disabled="true"], [disabled] *, [aria-disabled="true"] * { cursor: default; }
[role="separator"][aria-label^="Resize"] { cursor: ew-resize; }

/* Text isn't selectable, except where selecting it makes sense: text fields, and text marked
   [data-selectable] (a dialog's message, a notification, a toast's detail, an error's explanation, the calculator's
   result). Labels, titles and controls never highlight on a drag or a double-click. */
html { -webkit-user-select: none; user-select: none; }
input, textarea, [contenteditable]:not([contenteditable="false"]), [data-selectable], [data-selectable] * { -webkit-user-select: text; user-select: text; }

/* Light, everywhere it applies: things inside a light area that aren't glass panels of their own
   (Home's search, a button or chip on its own) take the light look too; a switch that's off is a white knob on a grey
   track; a dialog (always over the dimmed backdrop) is a thicker white so its message reads; and in Light mode the
   backdrop behind a dialog is a soft dim, not a dark one. */
.on-bright .b-toggle:not(.on) { background: rgba(20, 24, 45, 0.14); box-shadow: none; }
.on-bright .b-toggle:not(.on)::after { background: #ffffff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 0 0 0.5px rgba(0, 0, 0, 0.08); }
.b-dialog.on-bright, .on-bright .b-dialog { --glass: rgba(255, 255, 255, 0.82); }
/* The outline marking split view's active side sits on the wallpaper: white, or near-black in Light mode. */
:root { --split-outline: #ffffff; }
[data-theme="light"] { --scrim: rgba(20, 22, 35, 0.30); --split-outline: #121318; }

/* Files (boards FilesGrid, FilesList, FilesDetailsAutoHide). Grid tiles: a 4:3 picture (a thumbnail, or the item's
   icon, folders in yellow) and the name under it; List rows: Name, Date modified, Type, Size. Selected items use the
   one selected look (.b-files .is-selected); tiles grow a little. */
.b-ftile { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 8px 8px 10px; border-radius: var(--radius);
  transition: transform var(--dur-move) var(--ease-standard), background-color var(--dur-move) var(--ease-standard); }
.b-ftile:hover { box-shadow: var(--highlight-edge); }
.b-ftile.is-selected { transform: scale(1.03); }
.b-ftile .pic { position: relative; width: 100%; aspect-ratio: 4 / 3; border-radius: 12px; display: grid; place-items: center; background: center / cover no-repeat; }
.b-ftile .pic.has-art { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.22); }
.ficon { display: grid; place-items: center; }
.ficon .b-icon { width: 44px; height: 44px; stroke-width: 1.4; color: var(--ink-muted); }
.ficon.folder .b-icon { color: #f5c542; }
.on-bright .ficon.folder .b-icon { color: #d39a00; }
.b-ftile .play { position: absolute; inset: 0; display: grid; place-items: center; }
.b-ftile .play .b-icon { width: 30px; height: 30px; color: #ffffff; fill: #ffffff; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5)); }
.b-ftile .nm { max-width: 100%; padding-inline: 2px; font: 600 13px/16px var(--font-text); text-align: center; overflow: hidden; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.b-frow { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(150px, 1.2fr) minmax(110px, 1fr) 90px; align-items: center; gap: 12px;
  height: 40px; padding: 0 12px; border-radius: 12px; transition: background-color var(--dur-move) var(--ease-standard); }
.b-frow:not(.head):hover { box-shadow: var(--highlight-edge); }
.b-frow.head { height: 32px; }
.b-fhead { all: unset; display: flex; align-items: center; gap: 4px; font: 600 11px/16px var(--font-display); letter-spacing: 0.8px; text-transform: uppercase; color: var(--ink-muted); cursor: pointer; }
.b-fhead .b-icon { width: 12px; height: 12px; }
.b-frow .name { display: flex; align-items: center; gap: 10px; min-width: 0; }
.b-frow .name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.b-frow .name .b-icon { color: var(--ink-muted); }
.b-frow .b-num { font-size: 13px; }
.b-fpreview { aspect-ratio: 4 / 3; border-radius: var(--radius); background: var(--glass-inset) center / cover no-repeat; display: grid; place-items: center; box-shadow: var(--shadow-lift); }
.b-fkv { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; font-size: 13px; line-height: 18px; }
.b-fkv .b-num { overflow-wrap: anywhere; }

/* Files: the box dragged to select, a name being typed in place, and Details' stacked preview for several items. */
.b-fbox { position: absolute; z-index: 3; pointer-events: none; border-radius: 6px; border: 1px solid color-mix(in srgb, var(--accent) 80%, transparent);
  background: color-mix(in srgb, var(--accent) 16%, transparent); }
.b-frename { width: 100%; min-width: 0; box-sizing: border-box; padding: 3px 6px; border-radius: 8px; outline: none; font: 600 13px/18px var(--font-text);
  color: var(--ink); background: var(--glass-inset); border: 1px solid color-mix(in srgb, var(--accent) 70%, transparent); }
.on-bright .b-frename { background: #ffffff; }
.b-fstack { position: relative; aspect-ratio: 4 / 3; }
.b-fstack > span { position: absolute; left: calc(var(--k) * 17%); top: calc(var(--k) * 12%); width: 64%; aspect-ratio: 4 / 3; border-radius: 14px;
  background: var(--glass-inset) center / cover no-repeat; box-shadow: var(--shadow-lift); display: grid; place-items: center; }

/* Files: dragging. The folder or place a drag would land in shows an accent outline; dropping on the file panel itself
   (the folder Files shows) outlines the panel; a chip with the count follows the pointer. */
.b-files .is-drop { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 85%, transparent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.is-drop-area { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 70%, transparent); }
.b-fghost { position: fixed; z-index: 30; pointer-events: none; display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 12px 0 12px;
  border-radius: 12px; font: 650 14px/18px var(--font-text); color: var(--ink); background: rgba(20, 20, 30, 0.82);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 10px 24px rgba(0, 0, 0, 0.35); }
.b-fghost .b-icon { width: 16px; height: 16px; }
.b-fghost b { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; display: grid; place-items: center; font: 700 12px/1 var(--font-text);
  color: var(--on-accent); background: var(--accent); }
/* Search results: the name over its folder's path, and the size. */
.b-frow.res { grid-template-columns: minmax(0, 1fr) 90px; height: 54px; }
.b-frow.res .two { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.b-frow.res .two > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.b-frow.res small { font-size: 12px; line-height: 16px; }

/* Files › Recycle Bin: Name, Original location, Date deleted, Size, and Restore on the selected or pointed-at row. */
.b-frow.bin { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.3fr) 150px 80px 96px; }
.b-frow.bin .act { display: flex; justify-content: flex-end; visibility: hidden; }
.b-frow.bin:hover .act, .b-frow.bin.is-selected .act { visibility: visible; }
.b-frow.bin .act .b-btn { min-width: 0; height: 30px; padding: 0 14px; }

/* Files' viewer (boards FilesViewImage, FilesViewVideo, FilesViewPdf): one glass panel over Files (or the whole window
   in full screen); the header; the stage with the file, previous / next arrows, and a floating glass bar. */
.b-viewer { position: absolute; inset: 0; z-index: 8; display: flex; flex-direction: column; gap: 10px; padding: 12px 14px 14px; box-shadow: var(--shadow-edge-light), var(--shadow-float); }
/* Full screen: the whole window, black behind the picture, nothing of Bridge showing; same header and tools. */
.b-viewer.full { position: fixed; inset: 0; z-index: 15; border-radius: 0; border-color: transparent; background: #000000; box-shadow: none; }
.b-viewer.full .stage { border-radius: 10px; background: #000000; }
.b-viewer > header { display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 4px; }
.b-viewer > header .nm { font: 650 16px/20px var(--font-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.b-viewer .stage { position: relative; flex: 1; min-height: 0; display: flex; border-radius: 14px; overflow: hidden; background: rgba(0, 0, 0, 0.22); }
.b-viewer .pic { position: relative; flex: 1; min-width: 0; overflow: hidden; }
.b-viewer .pic img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; transition: transform var(--dur-move) var(--ease-standard); user-select: none; }
.b-viewer .vid { flex: 1; min-width: 0; width: 100%; height: 100%; object-fit: contain; background: #000000; }
.b-varrow { all: unset; position: absolute; top: 50%; z-index: 3; width: 40px; height: 40px; margin-top: -20px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: #ffffff; background: rgba(14, 14, 20, 0.45); backdrop-filter: blur(12px); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22); }
.b-varrow.left { left: 16px; } .b-varrow.right { right: 16px; }
.b-varrow:hover { background: rgba(14, 14, 20, 0.6); }
.b-vbar { position: absolute; left: 50%; bottom: 16px; z-index: 3; transform: translateX(-50%); display: flex; align-items: center; gap: 4px; padding: 4px 8px; border-radius: 14px; }
.b-vbar.wide { left: 24px; right: 24px; transform: none; gap: 12px; padding: 6px 14px; }
.b-vbar .sep { width: 1px; height: 20px; margin: 0 4px; background: var(--glass-edge); }
.b-vzoom { all: unset; min-width: 44px; text-align: center; font-weight: 650; cursor: pointer; }
.b-vthumbs { width: 104px; flex: none; overflow-y: auto; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 12px 8px; background: rgba(0, 0, 0, 0.12); }
.b-vthumbs .th { all: unset; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px; border-radius: 12px; }
.b-vthumbs .th > span { width: 64px; border-radius: 3px; background: #ffffff center / 100% 100% no-repeat; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); }
.b-vthumbs .th.is-selected { background: var(--selected); box-shadow: var(--selected-edge); }
.b-viewer .pdf { flex: 1; min-width: 0; overflow: auto; display: flex; justify-content: center; align-items: flex-start; padding: 32px 24px 90px; }
.b-viewer .pdf .sheet { flex: none; background: #ffffff center / 100% 100% no-repeat; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); }
/* While the viewer is open, the panels under it go (glass over glass would show them through). */
.b-files.viewing > :not(.b-viewer) { display: none !important; }

/* The picture editor (the viewer's Edit mode): the tool rail, the picture with crop box and marks, the 280px inspector. */
.b-viewer > header .b-seg { flex: none; }
.b-vsep { width: 1px; height: 20px; margin: 0 4px; background: var(--glass-edge); flex: none; }
.b-vedit { flex: 1; min-height: 0; display: flex; gap: 10px; }
.b-vrail { flex: none; width: 52px; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px 0; border-radius: 14px; background: var(--glass-lift); }
.b-vrail .is-selected { background: var(--selected); box-shadow: var(--selected-edge); }
.b-vedit .ed-area { align-items: center; justify-content: center; }
.ed-frame { position: relative; flex: none; touch-action: none; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); }
.ed-frame canvas { display: block; width: 100%; height: 100%; }
.ed-frame.tool-draw, .ed-frame.tool-shapes { cursor: crosshair; }
.ed-frame.tool-text { cursor: text; }
.ed-crop { position: absolute; cursor: move; box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.9);
  background: linear-gradient(rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.35)) 33.33% 0 / 1px 100% no-repeat,
    linear-gradient(rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.35)) 66.66% 0 / 1px 100% no-repeat,
    linear-gradient(rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.35)) 0 33.33% / 100% 1px no-repeat,
    linear-gradient(rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.35)) 0 66.66% / 100% 1px no-repeat; }
.ed-crop .h { position: absolute; width: 16px; height: 16px; border-radius: 4px; background: #ffffff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); }
.ed-crop .nw { left: -8px; top: -8px; cursor: nwse-resize; } .ed-crop .se { right: -8px; bottom: -8px; cursor: nwse-resize; }
.ed-crop .ne { right: -8px; top: -8px; cursor: nesw-resize; } .ed-crop .sw { left: -8px; bottom: -8px; cursor: nesw-resize; }
.ed-picked { position: absolute; pointer-events: none; margin: -4px; padding: 4px; outline: 1.5px dashed var(--accent); border-radius: 4px; }
.b-vinspector { flex: none; width: 280px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; padding: 14px; border-radius: 14px; background: var(--glass-lift); }
.b-vinspector .ed-title { font: 650 16px/20px var(--font-text); }
.ed-group { display: flex; flex-direction: column; gap: 10px; }
.ed-group > summary { cursor: pointer; list-style: none; padding: 4px 0; }
.ed-group > summary::-webkit-details-marker { display: none; }
.ed-group[open] > summary { margin-bottom: 6px; }
.ed-slider { display: grid; grid-template-columns: 1fr auto; gap: 4px 8px; align-items: center; }
.ed-slider > .b-slider, .ed-slider > :last-child { grid-column: 1 / -1; }
.ed-buttons { display: flex; gap: 8px; } .ed-buttons > * { flex: 1; }
.ed-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.ed-swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.ed-swatches .b-swatch { all: unset; width: 24px; height: 24px; border-radius: 50%; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3), 0 1px 3px rgba(0, 0, 0, 0.3); }
.ed-swatches .b-swatch.is-selected { box-shadow: 0 0 0 2px var(--glass), 0 0 0 4px var(--accent); }
.ed-filters { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ed-filters .f { all: unset; cursor: pointer; display: flex; flex-direction: column; gap: 4px; padding: 6px; border-radius: 12px; text-align: center; }
.ed-filters .f > span { aspect-ratio: 4 / 3; border-radius: 8px; background: rgba(0, 0, 0, 0.2) center / cover no-repeat; }
.ed-filters .f.is-selected { background: var(--selected); box-shadow: var(--selected-edge); }
.ed-size { display: flex; gap: 8px; } .ed-size label { flex: 1; display: flex; flex-direction: column; gap: 4px; } .ed-size .b-field { min-width: 0; }
.ed-toggle { display: flex; align-items: center; justify-content: space-between; }

/* The video editor: the video (cropped and turned by CSS while editing), the filmstrip timeline under it with accent
   trim handles, the kept parts and the playhead, and the saving progress. */
.vs-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.vs-frame { overflow: hidden; background: #000000; }
.vs-turn { position: absolute; left: 50%; top: 50%; overflow: hidden; transition: transform var(--dur-move) var(--ease-standard); }
.vs-turn video { position: absolute; max-width: none; }
.vs-text { position: absolute; white-space: pre; font-family: "Segoe UI Variable Display", "Segoe UI", sans-serif; font-weight: 600; line-height: 1.2; pointer-events: none; }
.vs-text.live { pointer-events: auto; cursor: move; }
.vs-text.is-picked { outline: 1.5px dashed var(--accent); outline-offset: 4px; border-radius: 4px; }
.vs-time { flex: none; display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 14px; background: var(--glass-lift); }
.vs-strip { position: relative; flex: 1; height: 52px; border-radius: 8px; cursor: pointer; touch-action: none; }
.vs-frames { position: absolute; inset: 0; display: flex; border-radius: 8px; overflow: hidden; background: rgba(0, 0, 0, 0.4); filter: brightness(0.45) saturate(0.6); }
.vs-frames canvas { flex: 1; min-width: 0; height: 100%; object-fit: cover; }
.vs-part { position: absolute; top: 0; bottom: 0; overflow: hidden; border-radius: 6px; box-shadow: inset 0 0 0 2px var(--accent); backdrop-filter: brightness(2.2) saturate(1.6); }
.vs-part.is-picked { box-shadow: inset 0 0 0 2px #ffffff, inset 0 0 18px rgba(var(--accent-rgb), 0.9); }
.vs-handle { position: absolute; top: -4px; bottom: -4px; width: 12px; margin-left: -6px; border-radius: 4px; cursor: ew-resize; z-index: 2;
  background: var(--accent); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35); }
.vs-head { position: absolute; top: -8px; bottom: -8px; width: 2px; margin-left: -1px; background: #ffffff; border-radius: 1px; z-index: 3; pointer-events: none; box-shadow: 0 0 6px rgba(0, 0, 0, 0.5); }
.vs-saving { position: absolute; left: 50%; bottom: 20px; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; padding: 8px 12px 8px 16px; border-radius: 14px; z-index: 4; }
.vs-bar { width: 180px; height: 6px; border-radius: 3px; background: var(--glass-lift-strong); overflow: hidden; }
.vs-bar > i { display: block; height: 100%; background: var(--accent); transition: width 200ms linear; }

/* The PDF editor: draggable page thumbnails, the page with its marks (SVG), text, notes and form fields on top, the
   signature pad and Combine's list in the inspector. */
.pe-thumbs { border-radius: 14px; }
.pe-thumbs .th.is-dragging { opacity: 0.4; }
.pe-thumbs .th > span { transition: transform var(--dur-move) var(--ease-standard); }
.pe-area { overflow: auto; align-items: center; justify-content: center; }
.pe-sheet { position: relative; flex: none; background: #ffffff; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); transition: transform var(--dur-move) var(--ease-standard); }
.pe-sheet > img { position: absolute; inset: 0; width: 100%; height: 100%; user-select: none; pointer-events: none; }
.pe-marks { position: absolute; inset: 0; touch-action: none; }
.pe-marks.tool-select { cursor: default; } .pe-marks.tool-comment, .pe-marks.tool-sign { cursor: copy; }
.pe-marks.tool-edit, .pe-marks.tool-highlight, .pe-marks.tool-draw, .pe-marks.tool-shapes, .pe-marks.tool-redact { cursor: crosshair; }
.pe-marks .pe-picked { filter: drop-shadow(0 0 2px var(--accent)) drop-shadow(0 0 2px var(--accent)); }
.pe-text { position: absolute; white-space: pre; pointer-events: none; font-family: "Segoe UI", sans-serif; line-height: 1.2; }
.pe-text.sig { font-family: "Segoe Script", cursive; }
.pe-text.is-picked { outline: 1.5px dashed var(--accent); outline-offset: 3px; }
.pe-note { position: absolute; width: 22px; height: 22px; margin: -2px; display: grid; place-items: center; font-size: 14px; cursor: pointer; border-radius: 6px; background: #ffc83d; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); }
.pe-note.is-picked { box-shadow: 0 0 0 2px var(--accent), 0 2px 6px rgba(0, 0, 0, 0.3); }
.pe-field { position: absolute; box-sizing: border-box; margin: 0; padding: 0 4px; border: 1px solid rgba(61, 155, 255, 0.7); border-radius: 2px; background: rgba(61, 155, 255, 0.12); color: #111114; font-family: "Segoe UI", sans-serif; outline: none; resize: none; }
.pe-field:focus { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.12); }
input[type="checkbox"].pe-field { padding: 0; accent-color: var(--accent); }
.pe-pad { width: 100%; height: 96px; border-radius: 10px; background: #ffffff; touch-action: none; cursor: crosshair; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12); }
.pe-combine { display: flex; flex-direction: column; gap: 8px; }
.pe-combine .ed-toggle > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Games (boards GamesRow, GamesGrid, GamesDetails): the hero info over the hero backdrop (drawn into the wallpaper by
   the host), the library bar, the shelf or grid of 2:3 covers, Details. Covers, title, buttons and bar share one
   left edge. */
.g-page { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 16px; }
/* Over a full-screen hero: a scrim darkens the bottom and left, where the details, buttons and covers sit. */
.g-page.row::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(0deg, rgba(5, 7, 12, 0.82) 0%, rgba(5, 7, 12, 0.45) 38%, transparent 62%), linear-gradient(90deg, rgba(5, 7, 12, 0.55) 0%, transparent 45%); }
.g-hero { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.g-badges { display: flex; gap: 8px; }
.b-badge.warn { background: rgba(255, 200, 61, 0.22); color: #ffd36b; }
.on-bright .b-badge.warn, .on-bright.b-badge.warn { color: #9a5a00; }
.g-title { margin: 4px 0 0; font: 700 56px/1.05 var(--font-display); letter-spacing: -0.5px; text-shadow: 0 2px 18px rgba(0, 0, 0, 0.45); }
.g-logo { display: block; max-width: 480px; max-height: 130px; margin: 6px 0 2px; object-fit: contain; object-position: left center; filter: drop-shadow(0 4px 16px rgba(0, 0, 0, 0.5)); }
.g-stats { display: flex; gap: 32px; margin: 8px 0 6px; }
.g-stats dt { font-size: 12px; opacity: 0.8; }
.g-stats dd { margin: 2px 0 0; font: 600 20px/1.2 var(--font-mono); text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5); }
.g-actions { display: flex; gap: 8px; }
.g-actions .b-btn { height: 60px; font-size: 18px; border-radius: 16px; }
.g-actions .g-play { padding: 0 36px; box-shadow: 0 0 24px rgba(var(--accent-rgb), 0.55), var(--shadow-edge-light); }
.g-actions .g-big { padding: 0 30px; }
.g-actions .b-icon-btn.g-big { width: 60px; padding: 0; }
.g-star.on { color: #ffc83d; }
.g-bar { display: flex; align-items: center; }
/* Row: the hero, the Recent / Favourites / A-Z switch and the search field share one grid. Its first column is exactly as wide as the
   buttons, and the logo (or a wrapped title), the stats and the switch all fill that width. The bar and the row sit
   at the bottom whether or not a game is shown. */
/* The hero's column is exactly the button row's width (Play 170 + Details 190 + star 60 + gaps), with or without a game. */
.g-page.row > .g-top { margin-top: auto; display: grid; grid-template-columns: 436px 1fr; row-gap: 16px; align-items: center; }
.g-top > .g-hero { grid-column: 1; }
.g-top > .g-barL { grid-column: 1; grid-row: 2; }
.g-top > .g-barL, .g-top > .g-barR { display: flex; align-items: center; }
.g-page.grid .g-shelf { scrollbar-gutter: stable; }   /* the scrollbar's room is kept with few games too, so the covers never resize on a filter */   /* no text baseline: the row is the same height whichever filter is chosen */
.g-top > .g-barR { grid-column: 2; grid-row: 2; justify-self: end; }
.g-top .g-logo, .g-top .g-title, .g-top .g-stats, .g-barL .b-seg { width: 0; min-width: 100%; }   /* they take the column's width, they never set it */
/* The title block is always the same height (and the badge row is always there), so changing the filter or the game never moves
   the buttons: the logo fits it, a title wraps to at most three lines. */
.g-top .g-badges { min-height: 20px; }
.g-top .g-logo { max-width: none; max-height: none; height: 132px; object-fit: contain; object-position: left bottom; }
.g-top .g-title { height: 132px; margin: 0; display: flex; align-items: flex-end; font-size: 40px; line-height: 1.1; overflow-wrap: anywhere; }
.g-top .g-title > span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.g-top .g-stats { justify-content: space-between; flex-wrap: wrap; gap: 12px 24px; }
.g-shelf { flex: 1; min-height: 0; }   /* it is a .b-scroll.tiles: the catch-all .b-scroll padding rule must not shrink its gutters */
/* The row and the grid keep a gutter as deep as a grown cover and its shadow (cancelled by a negative margin), so nothing is cut off. */
.g-page.row .g-shelf { flex: none; min-height: calc(var(--cover-w, 250px) * 1.5 + 90px); display: flex; gap: 28px; overflow-x: auto; overflow-y: hidden; padding: 32px 16px 44px; margin: -16px -16px 0; align-items: flex-start; }   /* top: clear of the library bar; bottom: inside the window (the page clips there) */
/* The scrollbar's ends sit on the page's content edges (the shelf reaches 32px past them for the grown covers), and it ends where the page does,
   16px above the window's edge, like every panel in Bridge. */
.g-page.row .g-shelf::-webkit-scrollbar-track { margin: 0 16px; }
/* On the row the scrollbar is always there (not only while the pointer is over the row or it's scrolling): it shows how
   far along your games you are. */
.b-app .g-page.row .g-shelf:not(:hover):not(.is-scrolling)::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.28); }
:root[data-input=pad] .g-page.row .g-shelf::-webkit-scrollbar { display: none; }   /* the scrollbar is for mouse and keyboard; a controller moves along the row */
.g-page.grid .g-shelf { display: grid; grid-template-columns: repeat(var(--grid-cols, auto-fill), var(--grid-w, var(--cover-w, 250px))); justify-content: space-between; gap: 20px; align-content: start; overflow-y: auto; padding: 28px 28px 36px; margin: -20px -28px -28px; }
.g-gridbody { flex: 1; min-height: 0; display: flex; gap: 16px; position: relative; }
/* The grid is its own glass panel, with the library bar inside it. */
.g-gridpanel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; padding: 16px; gap: 12px; }
.g-page.grid .g-gridpanel .g-shelf { flex: 1; min-height: 0; margin: -8px -16px -16px; padding: 24px 28px 28px; }
.g-cover { position: relative; flex: none; width: var(--cover-w, 250px); height: calc(var(--cover-w, 250px) * 1.5);   /* exactly the 2:3 cover shape */ border-radius: 14px; overflow: hidden; cursor: pointer;
  background: center / cover no-repeat; box-shadow: var(--shadow-glass); transform-origin: center; transition: transform var(--dur-panel) var(--ease-spring), box-shadow var(--dur-move) var(--ease-standard); }
.g-page.grid .g-cover { transform-origin: center; }   /* the size is the Settings cover size, as in the row */
/* Rows are as tall as the covers, set outright (3/2 of the width): never measured, so never cut or overlapping. */
.g-page.grid .g-shelf { grid-auto-rows: calc(var(--grid-w, var(--cover-w, 250px)) * 1.5); }   /* --grid-w: the cover width that fills the row (set by the page) */
.g-page.grid .g-cover { width: var(--grid-w, var(--cover-w, 250px)); height: calc(var(--grid-w, var(--cover-w, 250px)) * 1.5); }
/* In the row the selected cover grows from its middle; only the first and last games grow toward the edge of the screen. */
.g-page.row .g-cover:first-child { transform-origin: left center; }
.g-page.row .g-cover:last-child { transform-origin: right center; }
.g-page.row .g-cover:only-child { transform-origin: left center; }   /* a lone cover is the first and the last: it stays on the page's left margin like the first cover, growing to the right */
.g-cover.is-selected { transform: scale(1.08); z-index: 1; box-shadow: var(--selected-edge); }   /* no drop shadow: it can't be seen on the dark backing, so it takes no room */
.g-page.grid .g-cover.is-selected { transform: scale(1.04); }
.g-cover > .b-badge { position: absolute; left: 10px; top: 10px; }
.g-cover > .nm { position: absolute; left: 14px; right: 14px; bottom: 14px; font: 650 18px/1.25 var(--font-text); text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6); }
.g-hover { position: absolute; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; gap: 8px; padding: 48px 12px 12px; opacity: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.78)); color: #ffffff; transition: opacity var(--dur-press) var(--ease-standard); }
.g-hover > b { font: 650 16px/1.25 var(--font-text); }
.g-hover > div { display: flex; gap: 6px; }
.g-page.grid .g-cover:hover .g-hover { opacity: 1; }
.g-page.grid .g-cover:hover > .nm { opacity: 0; }
/* In the grid, any highlighted game shows its name and buttons (FIXES #66): pointed at, controller focus, and the
   selected one. The row has no overlay on its covers: the hero above shows the game and its buttons (Nov 8). */
.g-page.grid .g-cover.is-pad-focus .g-hover, .g-page.grid .g-cover.is-selected .g-hover { opacity: 1; }
.g-page.grid .g-cover.is-pad-focus > .nm, .g-page.grid .g-cover.is-selected > .nm { opacity: 0; }
/* Nothing to show: a quiet message where the covers would be, as tall as a cover so nothing around it moves. */
.g-empty { flex: none; height: calc(var(--cover-w, 250px) * 1.5); display: flex; flex-direction: column; justify-content: center; gap: 8px; padding: 0 4px; }
.g-empty b { font: 650 22px/1.2 var(--font-display); }
.g-empty span { font-size: 16px; }
.g-page.grid .g-empty { grid-column: 1 / -1; height: auto; padding: 24px 4px; }
.g-modal { position: fixed; inset: 0; z-index: 12; display: grid; place-items: center; background: var(--scrim, rgba(0, 0, 0, 0.45)); }
.g-details { width: 580px; }
.g-dtop { display: flex; gap: 20px; }
.g-dcover { flex: none; width: 160px; aspect-ratio: 2 / 3; border-radius: 12px; background: center / cover no-repeat; box-shadow: var(--shadow-glass); }
.g-dinfo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.g-dinfo h2 { margin: 0; font: 700 28px/1.15 var(--font-display); }
.g-dinfo dd { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Games: a running game's hero buttons, Change art (board GamesChangeArt). */
.g-actions .g-running { pointer-events: none; }
/* the two buttons keep one size whatever they say (Play/Running, Details/Close game) */
.g-actions .g-slot1 { width: 170px; padding: 0; justify-content: center; }
.g-actions .g-slot2 { width: 190px; padding: 0; justify-content: center; }
.g-art { width: 760px; max-height: calc(100vh - 120px); }
.g-arthead { display: flex; align-items: center; gap: 12px; font-size: 18px; }
.g-artgrid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; max-height: 400px; min-height: 160px; overflow-y: auto; padding: 4px; align-content: start; }
.g-artgrid.hero { grid-template-columns: repeat(2, 1fr); }
.g-artgrid.logo { grid-template-columns: repeat(3, 1fr); }
.g-artitem { all: unset; cursor: pointer; aspect-ratio: 2 / 3; border-radius: 10px; background: rgba(0, 0, 0, 0.25) center / cover no-repeat; box-shadow: var(--shadow-glass); transition: transform var(--dur-move) var(--ease-standard); }
.g-artgrid.hero .g-artitem { aspect-ratio: 96 / 31; }
.g-artgrid.logo .g-artitem { aspect-ratio: 2 / 1; background-size: contain; background-color: rgba(0, 0, 0, 0.35); }
.g-artitem.is-selected { transform: scale(1.04); box-shadow: var(--selected-edge); }
.g-artkey { display: flex; flex-direction: column; gap: 12px; padding: 8px 0; }

/* Home and its results (board HomeSearch): the 58px field a little above the middle, at most 640px; results 8px below,
   the field's width, at most 340px tall, in groups. Shared by Overview's search. */
/* Home's search rests in the centre of the screen (Home.tsx moves it there from the top) and rises as you type. */
.h-home { flex: 1; display: flex; justify-content: center; padding-top: 0; }
.h-box { position: relative; width: 100%; max-width: 640px; height: 58px; }
.h-box.is-placed, .nt-search { transition: transform var(--dur-panel) var(--ease-standard); }
.h-results { position: absolute; left: 0; right: 0; top: calc(100% + 8px); z-index: 5; padding: 8px; box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.h-scroll { max-height: 324px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.h-group { padding: 10px 12px 4px; }
.h-row { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 6px 12px; border-radius: 12px; cursor: pointer; }
.h-row.game { min-height: 56px; }
.h-row.is-selected { background: var(--selected); box-shadow: var(--selected-edge); }
.h-row .h-cover { flex: none; width: 28px; height: 42px; border-radius: 6px; background: rgba(0, 0, 0, 0.25) center / cover no-repeat; }
.h-row .h-img { flex: none; width: 22px; height: 22px; object-fit: contain; border-radius: 5px; }
.h-row .h-ico { flex: none; width: 22px; display: grid; place-items: center; opacity: 0.85; }
.h-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.h-text b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-text small { font-size: 12px; opacity: 0.75; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-action { flex: none; font-size: 12px; opacity: 0.7; }

/* Overview (boards Overview, OverviewBackground, AllApps): search at the top, window cards grouped by screen, the dock
   at the bottom centre; the live pictures are drawn by the host into each card's frame. */
.ov { position: fixed; inset: 0; z-index: 9; display: flex; flex-direction: column; align-items: center; padding: 24px 48px 0; gap: 18px; animation: ov-in var(--dur-panel) var(--ease-enter); }
@keyframes ov-in { from { opacity: 0; transform: scale(0.98); } }
.ov-search { position: relative; width: 480px; max-width: 100%; height: 46px; flex: none; }
.ov-cards { flex: 1; min-height: 0; width: 100%; overflow-y: auto; display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 8px 0 24px; }
.ov-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 28px; }
.ov-display { margin-top: 6px; }
.ov-card { width: 320px; display: flex; flex-direction: column; gap: 8px; cursor: pointer; border-radius: 16px; padding: 6px; transition: transform var(--dur-move) var(--ease-standard); }
.ov-card:hover, .ov-card:focus-visible { transform: scale(1.04); outline: none; box-shadow: var(--highlight-edge); }
.ov-head { display: flex; align-items: center; gap: 10px; height: 32px; padding: 0 4px; }
.ov-head img { width: 24px; height: 24px; border-radius: 6px; }
.ov-head b { flex: 1; min-width: 0; font: 650 16px/20px var(--font-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-shadow: 0 1px 8px rgba(0, 0, 0, 0.45); }
.ov-mark { width: 24px; height: 24px; display: grid; place-items: center; }
.ov-x { opacity: 0; transition: opacity var(--dur-press) var(--ease-standard); }
.ov-card:hover .ov-x, .ov-card:focus-within .ov-x { opacity: 1; }
.ov-thumb { aspect-ratio: 16 / 10; border-radius: 14px; display: grid; place-items: center; box-shadow: var(--shadow-edge-light), var(--shadow-glass); }
.ov-self span { font: 650 18px/1 var(--font-display); opacity: 0.85; }
.ov-title { padding: 0 6px; font-size: 12px; opacity: 0.7; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-none { padding: 24px; }
.ov-dock { flex: none; display: flex; align-items: center; gap: 10px; padding: 12px 16px; margin-top: auto; margin-bottom: 24px; border-radius: 20px; box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.ov-app { all: unset; width: 48px; height: 48px; display: grid; place-items: center; border-radius: 14px; cursor: pointer; transition: transform var(--dur-move) var(--ease-standard); }
.ov-app:hover, .ov-app:focus-visible { transform: scale(1.12); box-shadow: var(--highlight-edge); }
.ov-app img { width: 36px; height: 36px; object-fit: contain; }
.ov-app span { font: 700 20px/1 var(--font-display); }
.ov-sep { width: 1px; height: 32px; background: var(--glass-edge); }
.ov-dockbtn { width: 48px; height: 48px; }
.ov-bgwrap { position: relative; }
.ov-count { position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; display: grid; place-items: center; font-size: 11px; background: var(--glass-lift-strong); box-shadow: var(--shadow-edge-light); }
.ov-bgpanel { position: fixed; bottom: 112px; left: calc(50% + 40px); width: 300px; padding: 12px; display: flex; flex-direction: column; gap: 4px; z-index: 10; box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.ov-bgrow { display: flex; align-items: center; gap: 10px; height: 44px; padding: 0 6px 0 10px; border-radius: 12px; cursor: pointer; }
.ov-bgrow:hover { box-shadow: var(--highlight-edge); }
.ov-bgrow img { width: 22px; height: 22px; }
.ov-bgrow span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* All apps in the open apps' place (FIXES #90), straight on the backdrop like GNOME's app grid. */
.ov-apps { flex: 1; min-height: 0; width: min(1240px, 100%); overflow-y: auto; overflow-x: hidden; padding: 8px 0 24px; animation: ov-apps-in var(--dur-panel) var(--ease-enter); }
@keyframes ov-apps-in { from { opacity: 0; transform: scale(0.96); } }
.ov-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 12px 8px; padding: 4px; }
.ov-gapp { all: unset; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 12px 6px; border-radius: 14px; cursor: pointer; text-align: center; }
.ov-gapp:hover, .ov-gapp:focus-visible { box-shadow: var(--highlight-edge); }
.ov-gapp img, .ov-gapp .ov-letter { width: 64px; height: 64px; }
.ov-gapp img { object-fit: contain; }   /* every app's icon at 128px from the shell, shown the same size (FIXES #50) */
.ov-gapp .ov-letter { display: grid; place-items: center; border-radius: 12px; font: 700 20px/1 var(--font-display); background: var(--glass-lift-strong); }
.ov-gapp small { font-size: 13px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-shadow: 0 1px 3px rgb(0 0 0 / 0.45); }

/* The start screen (boards StartLoading, StartClock): the logo above the name, centred and bigger while loading (the
   mark traces on, then pulses until everything is ready; at least 2 s), then gliding up to its place above the frosted clock. */
.st { position: fixed; inset: 0; z-index: 30; display: grid; place-items: center; transition: opacity 230ms var(--ease-exit); }
.st.leaving { opacity: 0; }
.st-stack { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.st-brand { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.st:not(.loading) .st-brand { transition: transform 900ms var(--ease-standard); }   /* the glide up to the clock, not at the first paint */
.st.loading .st-brand { transform: translateY(var(--dy, 0px)) scale(2.2); }
/* Clearly visible on any wallpaper (the loading logo was hard to see): a lightened accent, a dark shadow under
   it, and a soft dark pool behind it while loading. */
.st::before { content: ''; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(closest-side at 50% 50%, rgba(0, 0, 0, 0.5), transparent); background-size: 900px 900px; background-repeat: no-repeat; background-position: center; opacity: 0; transition: opacity 500ms var(--ease-standard); }
.st.loading::before { opacity: 1; }
.st-brand svg { width: 84px; height: 59px; overflow: visible; filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.55)); }
.st-brand path { stroke: color-mix(in srgb, var(--accent) 60%, #ffffff); stroke-dasharray: 100; stroke-dashoffset: 100; animation: st-draw 1100ms var(--ease-standard) forwards; }
.st-brand rect { fill: color-mix(in srgb, var(--accent) 60%, #ffffff); transform-origin: center; transform: scaleX(0); animation: st-deck 500ms 700ms var(--ease-standard) forwards; }
.st.loading .st-brand svg { animation: st-pulse 1600ms 1300ms ease-in-out infinite; }
@keyframes st-draw { to { stroke-dashoffset: 0; } }
@keyframes st-deck { to { transform: scaleX(1); } }
@keyframes st-pulse { 50% { filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 12px rgba(var(--accent-rgb), 0.9)); } }
.st-word { font: 400 24px/1 var(--font-brand); letter-spacing: 5px; opacity: 0; animation: st-fade 500ms 600ms forwards; text-shadow: 0 1px 10px rgba(0, 0, 0, 0.35); }
@keyframes st-fade { to { opacity: 1; } }
.st-under { display: flex; flex-direction: column; align-items: center; gap: 14px; transition: opacity 500ms 350ms var(--ease-standard); }
.st.loading .st-under { opacity: 0; transition: none; }
.st-date { font: 500 22px/1.2 var(--font-text); letter-spacing: normal; word-spacing: normal; opacity: 0.85; text-shadow: 0 1px 10px rgba(0, 0, 0, 0.4); }

/* Controller and keyboard focus: looks like hover (the highlight edge alone: no fill, no glow inside; decisions 146, 151). The on-screen keyboard
   (board Keyboard): 920px of glass at the bottom centre, three suggestions over one 11-column grid. */
.is-pad-focus { outline: none !important; box-shadow: var(--highlight-edge); border-radius: var(--radius, 12px); }
.g-cover.is-pad-focus, .ov-card.is-pad-focus, .ov-app.is-pad-focus { transform: scale(1.06); }
/* A primary (accent) button with controller focus (FIXES #64): the accent edge would vanish on it, so a white ring over a
   thin dark gap, and it grows a little, readable on any accent colour. */
.b-btn.primary.is-pad-focus { background-color: var(--accent); box-shadow: 0 0 0 2px rgba(10, 12, 18, 0.85), 0 0 0 4px #ffffff, var(--shadow-lift, 0 8px 24px rgba(0, 0, 0, 0.35)); transform: scale(1.05); }
.osk { position: fixed; left: 50%; bottom: 16px; z-index: 28; width: 920px; max-width: calc(100vw - 32px); transform: translateX(-50%); padding: 10px; display: flex; flex-direction: column; gap: 6px; box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.osk-sug { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.osk-row { display: grid; grid-template-columns: repeat(11, 1fr); gap: 6px; }
.osk-key { all: unset; height: 52px; border-radius: 12px; display: grid; place-items: center; font: 500 18px/1 var(--font-text); background: var(--glass-lift); cursor: pointer; box-shadow: inset 0 0 0 1px var(--glass-edge); }
.osk-sug .osk-key { height: 42px; font-size: 16px; }
.osk-key:hover { box-shadow: var(--highlight-edge); }
.osk-key.is-selected, .osk-key.is-on { background: var(--selected); box-shadow: var(--selected-edge); }
.osk-key.is-pad { background: var(--glass-lift-strong); box-shadow: var(--selected-edge); transform: scale(1.05); }
.osk-key:disabled { opacity: 0.35; }
.h-home, .ov-cards { padding-bottom: var(--osk-room, 0px); }

/* Settings (board Settings): the sidebar (Find a setting, sections) and the section panel. Groups are open while the
   section fits; only when it doesn't are just enough of them folded. */
.se-page { flex: 1; min-height: 0; display: flex; gap: 16px; }
.se-side { width: 300px; flex: none; padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.se-list { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 2px; }
.se-list .txt { display: flex; flex-direction: column; min-width: 0; }
.se-list .txt small { font-size: 12px; }
.se-main { flex: 0 1 560px; min-width: 0; padding: 20px 16px 16px; display: flex; flex-direction: column; gap: 12px; }   /* one card wide (FIXES #102) */
.se-title { margin: 0 16px 4px; font: 700 28px/1.2 var(--font-display); }
.se-groups { flex: 1; min-height: 0; }
/* The groups: cards in one stack, with room for their shadows inside the scrolling area. */
.se-cols { display: flex; flex-direction: column; gap: 18px; padding: 6px 12px 28px; }
.se-groups.b-scroll { padding-bottom: calc(8px + var(--osk-room, 0px)) !important; }
/* A group: a card exactly like the new tab's search bar (FIXES #98, #101, #102): the panel's glass shows through it (no
   tint or blur of its own), with that bar's clear edge, edge light and shadow; its name at the top, lines between rows. */
.se-group { flex: none; }
.se-rows-in { display: flex; flex-direction: column; padding: 4px 0; border-radius: var(--radius); }
.se-page .se-rows-in { background: transparent; border: 1px solid rgba(255, 255, 255, 0.26); box-shadow: var(--shadow-edge-light), var(--shadow-glass); }
.se-ctitle { padding: 12px var(--space-4) 2px; font: 600 12px/1.2 var(--font-text); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); }
.se-rows-in > .b-srow { position: relative; }
.se-rows-in > .b-srow + .b-srow::before, .se-rows-in > .b-srow + :not(.b-srow)::before { content: ''; position: absolute; left: var(--space-4); right: var(--space-4); top: 0; height: 1px; background: var(--glass-edge); }
.se-rows-in > .b-srow + :not(.b-srow) { position: relative; }
/* Rows aren't buttons (their controls are): no hover tint, no hand. Nothing in Settings grows when selected, so
   nothing reaches past the panel's edges. */
.se-page .b-srow { cursor: default; flex-wrap: wrap; row-gap: 8px; }
.se-page .b-srow > .txt { min-width: 220px; }
.se-page .b-srow > :last-child:not(.txt) { margin-left: auto; max-width: 100%; }
.se-page .b-item.is-selected, .se-page .b-srow.is-selected, .se-page .b-chip.is-selected { transform: none; }
/* A set of on/off buttons (Game overlay › Shows, FIXES #107): ordinary small buttons, as wide as their words. */
.se-toggles { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px; }   /* equal widths, filling the row */
.b-srow .se-toggles .b-btn:not(.b-icon-btn) { min-width: 0; padding-inline: 6px; }
.se-page .b-glass .se-toggles .b-btn.is-on { color: var(--ink); background: var(--selected); box-shadow: var(--selected-edge); }   /* on: the selected look, like a selected tab */
.se-page .b-glass .se-toggles .b-btn:not(.is-on) { color: var(--ink-muted); }
/* A wide control (a row of chips, a long switcher) sits under its title, full width (FIXES #106). */
.se-page .b-srow.se-wide { flex-direction: column; align-items: stretch; padding-block: 12px; }
.se-page .b-srow.se-wide > :last-child:not(.txt) { margin-left: 0; }
.se-page .b-srow.se-wide .b-seg { display: grid; width: 100%; }
.se-page .b-srow.se-wide .b-seg > span { padding-inline: 8px; }
/* A flyout's panel shown in Settings: one scroll (the section's), never a list scrolling inside it. */
.se-embed .b-scroll { max-height: none !important; overflow: visible; padding: 0 !important; margin: 0 !important; }
.se-flash { animation: se-flash 1.4s var(--ease-standard); }
@keyframes se-flash { 0%, 60% { background: var(--selected); box-shadow: var(--selected-edge); } }
.se-slider { display: flex; align-items: center; gap: 12px; width: 280px; }
.se-slider .b-slider, .se-slider > :first-child { flex: 1; }
.se-slider .b-num { min-width: 40px; text-align: right; }
.se-swatches { display: flex; gap: 10px; }
.se-swatches .b-swatch { all: unset; width: 26px; height: 26px; border-radius: 50%; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3); }
.se-swatches .b-swatch.is-selected { box-shadow: 0 0 0 2px var(--glass), 0 0 0 4px #ffffff; }
.se-swatches.is-off { opacity: 0.4; pointer-events: none; }
.se-pad { padding: 8px 16px 12px; }
.se-kv { padding: 8px 16px 12px; }
.se-rows-in > .se-pad, .se-rows-in > .se-kv, .se-rows-in > .se-drives { padding: 14px 16px; }
.se-log pre { margin: 0 0 10px; max-height: 320px; overflow: auto; padding: 12px; border-radius: 12px; background: rgba(0, 0, 0, 0.28); font: 12px/1.5 var(--font-mono); white-space: pre-wrap; }
.se-buttons { display: flex; gap: 8px; }
.se-stack { display: flex; flex-direction: column; gap: 10px; }   /* fields one under another, full width (FIXES #113) */
.b-kbd { font: 600 11px/1 var(--font-mono); padding: 4px 6px; border-radius: 6px; background: var(--glass-lift); opacity: 0.8; }

/* Settings › Wallpaper, Storage and the flyout panels shown inside Settings. */
.se-walls { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
.se-wall { all: unset; position: relative; aspect-ratio: 16 / 10; border-radius: 12px; cursor: pointer; background: rgba(0, 0, 0, 0.25) center / cover no-repeat; box-shadow: var(--shadow-glass); transition: transform var(--dur-move) var(--ease-standard); }
.se-wall:hover { transform: scale(1.03); box-shadow: var(--highlight-edge), var(--shadow-glass); }
.se-wall.is-selected { box-shadow: var(--selected-edge), var(--shadow-glass); }
.se-wall .b-badge { position: absolute; left: 8px; top: 8px; }
/* Delete: shows on hover (or keyboard focus), top right; red on its own hover. */
.se-wall .se-wall-x { position: absolute; right: 8px; top: 8px; opacity: 0; transform: scale(0.9); transition: opacity var(--dur-move) var(--ease-standard), transform var(--dur-move) var(--ease-standard);
  background: rgba(14, 14, 20, 0.62); }
.se-wall:hover .se-wall-x, .se-wall:focus-within .se-wall-x, .se-wall .se-wall-x:focus-visible { opacity: 1; transform: none; }
.se-wall .se-wall-x:hover { color: var(--danger); }
/* Bridge | Yours over the tiles; Bridge's own tiles carry their name along the bottom, on a shade that keeps it readable. */
.se-walls-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.se-wall-name { position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 10px 8px; border-radius: 0 0 12px 12px; font-weight: 600; font-size: 13px; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background: linear-gradient(180deg, transparent, rgba(5, 7, 12, 0.7)); pointer-events: none; }
.se-walls-empty { padding: 24px 4px 4px; }
.se-embed { padding: 0 4px; }
.se-embed .se-sublabel { padding: 12px 12px 4px; }
.se-slider.wide { width: 380px; gap: 8px; }
.se-slider.wide > :first-child { flex: none; }
.se-slider.wide > :nth-child(2) { flex: 1; }
.se-embed .b-srow { padding-inline: 12px; }
.se-drives { display: flex; flex-direction: column; gap: 14px; }
.se-drivehead { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.se-bar { height: 8px; border-radius: 4px; background: var(--glass-lift-strong); overflow: hidden; }
.se-bar > i { display: block; height: 100%; background: var(--accent); }

/* Settings › Games, Tabs: list lines, field rows, the Add launcher dialog (board SettingsAddLauncher). */
.se-line { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 4px 8px; border-radius: 10px; }
.se-line > .b-num { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.se-drag { cursor: grab; }
.se-grip { opacity: 0.5; letter-spacing: -3px; }
.se-frow { display: flex; gap: 8px; align-items: center; }
.se-flabel { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--ink-muted); }
.se-dialog { width: 560px; max-height: calc(100vh - 120px); overflow-y: auto; }
.se-dtitle { font: 650 18px/1.3 var(--font-text); }

/* The Server tab (boards Server, ServerAdd). */
.sv-page { flex: 1; min-height: 0; display: flex; gap: 16px; }
.sv-side { width: 400px; flex: none; padding: 14px; display: flex; flex-direction: column; gap: 12px; }
.sv-main { flex: 1; min-width: 0; padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.sv-none { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; text-align: center; }
.sv-none b { font: 650 22px/1.2 var(--font-display); }
.sv-head { display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 0 6px; font-size: 18px; }
.sv-head .b-muted { font-size: 14px; }
.sv-list { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
.sv-card { padding: 12px 14px; border-radius: 14px; background: var(--glass-lift); display: flex; flex-direction: column; gap: 10px; cursor: pointer; }
.sv-card.is-selected { background: var(--selected); box-shadow: var(--selected-edge); }
.sv-top { display: flex; align-items: center; gap: 8px; }
.sv-top .b-muted { font-size: 12px; }
.sv-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); flex: none; }
.sv-dot.running { background: #3ddc84; box-shadow: 0 0 8px rgba(61, 220, 132, 0.7); }
.sv-dot.crashed { background: #ff5c6c; }
.sv-buttons { display: flex; align-items: center; gap: 6px; }
.sv-log { flex: 1; min-height: 0; overflow: auto; padding: 12px 14px; border-radius: 12px; background: rgba(0, 0, 0, 0.3); font: 13px/1.6 var(--font-mono); white-space: pre-wrap; word-break: break-word; }
.sv-log .t { opacity: 0.5; }
.sv-log .warn { color: #ffcf5a; }
.sv-log .err { color: #ff7a85; }
.sv-cmd { display: flex; gap: 8px; }
.sv-apps { display: flex; flex-direction: column; gap: 8px; }
.sv-applist { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }

/* First-run setup (board Setup): one glass card per step with step dots, Back / Skip / Next. */
.su { position: fixed; inset: 0; z-index: 26; display: grid; place-items: center; }
/* The card is as tall as its step needs (never shorter than 580px), so nothing in it scrolls; only a window too small
   for a step lets that step's body scroll. */
.su-card { width: 800px; min-height: 580px; max-height: calc(100vh - 48px); display: flex; flex-direction: column; gap: 10px; padding: 28px 32px; }
.su-head { display: flex; align-items: center; }
.su-brand { display: flex; align-items: center; gap: 10px; font: 400 16px/1 var(--font-brand); letter-spacing: 3px; }
.su-brand svg { width: 28px; height: 20px; }
.su-dots { display: flex; gap: 6px; align-items: center; }
.su-dots i { width: 6px; height: 6px; border-radius: 3px; background: var(--ink-muted); opacity: 0.6; transition: width var(--dur-move) var(--ease-standard); }
.su-dots i.on { width: 20px; background: var(--ink); opacity: 1; }
.su-card h1 { margin: 18px 0 0; font: 700 28px/1.2 var(--font-display); }
.su-card p { margin: 0 0 6px; }
.su-body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; gap: 10px; }
.su-foot { display: flex; gap: 8px; align-items: center; }
.su-points { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 24px; }
.su-points div { display: flex; flex-direction: column; gap: 2px; }
.su-points b { font-weight: 600; }
.su-points span { font-size: 13px; line-height: 1.4; }
.su-foot .b-btn { min-width: 110px; }
.g-actions .g-stop { background: var(--danger); color: #fff; box-shadow: 0 0 24px rgba(255, 70, 70, 0.5), var(--shadow-edge-light); }

/* A page that failed (ui/guard.tsx): a calm message in the page's place. */
.b-guard { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; text-align: center; }
.b-guard b { font: 650 22px/1.2 var(--font-display); }
.b-guard .b-btn { margin-top: 8px; }

/* Motion (UI motion guide): selected tabs, chips and the logo grow on the soft spring. */
.b-tab, .b-chip, .b-logo { transition-property: transform, background-color, color, box-shadow; transition-duration: var(--dur-panel), var(--dur-move), var(--dur-move), var(--dur-move);
  transition-timing-function: var(--ease-spring), var(--ease-standard), var(--ease-standard), var(--ease-standard); }

/* Windows' "Animation effects" off: nothing moves or grows; things only fade, quickly. */
@media (prefers-reduced-motion: reduce) {
  :root { --select-grow: 1; --dur-move: 1ms; --dur-panel: 120ms; --dur-exit: 100ms; }
  *, *::before, *::after { animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
  .g-cover.is-selected, .b-item.is-selected, .b-srow.is-selected, .st.loading .st-brand { transform: none !important; }
}

/* A surface page held to the window's height scrolls as a whole; what's inside keeps its own height (it never squeezes
   to fit), so the page can always tell the shell how tall it really is. */
.sf-capped > * { flex-shrink: 0; }

/* Small windows (Bridge's smallest is 1100 x 720; with Text size at 140% that is 786 x 514 of room). Nothing is cut:
   the top bar's icons sit closer, side panels narrow, the Games hero gives the covers room, rows let controls shrink. */
.fl-places { width: 280px; padding: 16px 12px; overflow-y: auto; overflow-x: hidden; }
@media (max-width: 1000px) {
  .b-topbar .right { gap: 0; }
  .se-side { width: 230px; }
  .fl-places { width: 220px; }
}
.se-slider, .se-slider.wide { max-width: 100%; }
.se-page .b-srow .b-seg { max-width: 100%; }
.se-page .b-srow .b-seg > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.se-wall.is-selected { box-shadow: var(--selected-edge); }
/* Games row in a short window: first the stats go and the logo shrinks, then the logo goes and the buttons get smaller. */
@media (max-height: 820px) {
  .g-page.row .g-top .g-stats { display: none; }
  .g-page.row .g-top .g-logo, .g-page.row .g-top .g-title { height: 84px; font-size: 30px; }
}
@media (max-height: 620px) {
  .g-page.row .g-top .g-logo, .g-page.row .g-top .g-title, .g-page.row .g-top .g-badges { display: none; }
  .g-page.row .g-actions .b-btn { height: 44px; font-size: 16px; border-radius: 12px; }
  .g-page.row .g-actions .b-icon-btn.g-big { width: 44px; }
}

/* The browser's search suggestions (browser/suggest.tsx): a glass list under the field, the same rows as menus. */
.b-suggest-panel { position: absolute; left: 0; right: 0; top: calc(100% + 8px); z-index: 5; padding: 6px; border-radius: var(--radius); }
.b-suggest-panel.in-side { background: var(--glass-strong, rgba(14, 14, 20, 0.86)); box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.b-suggest { display: flex; flex-direction: column; gap: 2px; }
.b-suggest .b-item { height: 40px; cursor: pointer; }
.b-suggest .b-item .txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.b-suggest .b-item .txt b { font-weight: 600; }

/* Something set up and working (Settings › Games › SteamGridDB key): a quiet green check. */
.se-active { display: inline-flex; align-items: center; gap: 6px; color: var(--success); font-weight: 600; font-size: 13px; }

/* Narrow windows: what can step aside does, so nothing is cut. The top bar's date (the time stays), then its optional
   System and Tailscale icons; Files' Cut / Copy / Paste buttons (Ctrl+X / C / V and the right-click menu still have them),
   and its Details panel floats over the folder instead of squeezing it. */
.tb-extra { display: contents; }
@media (max-width: 1400px) { .tb-date { display: none; } }
@media (max-width: 900px) { .tb-extra { display: none; } .fl-clip { display: none; } .b-topbar .b-logo > span { display: none; } }
/* The smallest windows: now playing keeps its art (opens Music), play / pause and ×; previous and next go, then the
   Calculator icon, so the top bar's right side always fits (Bridge's smallest window at 140% text is 786px). */
@media (max-width: 900px) { .b-topbar .b-np [aria-label="Previous"], .b-topbar .b-np [aria-label="Next"] { display: none; } }
@media (max-width: 820px) { .b-topbar [aria-label="Calculator"] { display: none; } }
@media (max-width: 1000px) { .b-files > aside.b-panel { position: absolute; right: 0; top: 0; bottom: 0; z-index: 6; box-shadow: var(--shadow-edge-light), var(--shadow-float) !important; } }

/* Bridge's tooltip (tooltip.ts): a small dark glass label at the cursor; never Windows' own. */
.b-tip { position: fixed; z-index: 100; max-width: 360px; padding: 5px 9px; border-radius: 8px; pointer-events: none;
  background: rgba(14, 14, 20, 0.9); color: #f4f6fb; font: 500 12px/16px var(--font-text); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12), 0 4px 12px rgba(0, 0, 0, 0.35);
  opacity: 0; transform: translateY(-2px); transition: opacity var(--dur-move) var(--ease-standard), transform var(--dur-move) var(--ease-standard); white-space: pre-line; overflow-wrap: anywhere; }
.b-tip.is-shown { opacity: 1; transform: none; }

/* Text files in the viewer: the monospace face on a dark inset well, wrapped, the whole stage. */
.b-vtext { flex: 1; align-self: stretch; margin: 0; padding: 16px 20px; border: 0; border-radius: 12px; background: rgba(0, 0, 0, 0.28); color: var(--ink);
  font: 13px/20px var(--font-mono); white-space: pre-wrap; overflow-wrap: anywhere; overflow: auto; resize: none; outline: none; tab-size: 4; }
textarea.b-vtext:focus { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 60%, transparent); }
/* A row that shows only in some states (Settings: hidden while it would do nothing) fades in when it appears. */
.se-appear { animation: se-appear var(--dur-panel) var(--ease-enter); }
@keyframes se-appear { from { opacity: 0; transform: translateY(-4px); } }
/* Settings › Wi-Fi (FIXES #43): networks as rows; Other networks folds; joining opens the row into a panel. */
.se-wifi-ic { display: inline-flex; color: var(--ink-muted); }
.se-fold { cursor: pointer; }
.se-fold:hover, .se-fold:focus-visible { outline: none; box-shadow: var(--highlight-edge); }
.se-fold-ic { display: inline-flex; color: var(--ink-muted); transition: transform var(--dur-move) var(--ease-standard); }
.se-fold-ic.open { transform: rotate(180deg); }
.se-join { flex-direction: column; align-items: stretch; gap: 10px; padding-block: 12px; background: var(--glass-lift); animation: se-appear var(--dur-panel) var(--ease-enter); }
.se-join-head { display: flex; align-items: center; gap: var(--space-4); }
.se-join-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.se-why, .b-srow .txt .se-why { color: var(--danger); font-size: 12px; line-height: 16px; }
/* Games: the installed launchers as icon buttons beside the search (FIXES #25). */
.g-launchers { display: inline-flex; align-items: center; gap: 8px; margin-right: 8px; }
.g-launcher { width: 40px; height: 40px; padding: 0; justify-content: center; border-radius: var(--radius-round); }
.g-launcher.b-glass:hover, .g-launcher.b-glass:focus-visible { box-shadow: var(--highlight-edge), var(--shadow-glass); }
.g-launcher img { width: 24px; height: 24px; object-fit: contain; }
.g-launcher-letter { font: 700 15px/1 var(--font-display); }
.g-shelf.dragging { cursor: grabbing; user-select: none; scroll-behavior: auto; }
.g-shelf.dragging .g-cover { pointer-events: none; }
/* Overview's tray (FIXES #45): apps kept running with their windows hidden, marked by a dot under the icon. */
.ov-app.ov-tray, .ov-app.is-running { position: relative; }
/* An open app's dot under its icon in Overview's dock. */
.ov-app.is-running::after { content: ''; position: absolute; bottom: 3px; left: 50%; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: var(--ink); opacity: 0.85; }
.ov-app.ov-tray::after { content: ''; position: absolute; bottom: 3px; left: 50%; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: var(--accent); }
.ov-head .ov-x + .ov-x { margin-left: -6px; }
/* The D-pad in use hides the pointer over Bridge (FIXES #67); moving the pointer brings it back and clears the highlight. */
:root[data-input=pad], :root[data-input=pad] * { cursor: none !important; }
/* ...and nothing reacts to the hidden pointer (decision 149), so only the D-pad's highlight shows, not also a file the
   pointer happens to rest on. Moving the mouse shows it and gives it back at once (input/focus.ts). */
:root[data-input=pad] body * { pointer-events: none !important; }
/* The browser keeps what it had under the pointer as hovered until the mouse moves, so that leftover hover look is
   taken off while the D-pad is in use (the D-pad's own highlight, and anything selected or open, stay as they are). */
:root[data-input=pad] :is(button, a[href], summary, [role=button], [role=tab], [role=option], [role=switch], [role=radio], [role=menuitem], [data-click],
  .b-ftile, .b-frow, .b-tile, .b-item, .b-srow, .ov-card, .ov-app, .ov-gapp, .ov-bgrow, .se-wall, .se-fold, .osk-key):hover:not(.is-pad-focus, .is-selected, .is-open, [aria-selected="true"], [aria-checked="true"], [aria-current="page"], .primary) {
  background-color: transparent !important; box-shadow: none !important; transform: none !important; }
:root[data-input=pad] .b-btn:not(.quiet):not(.primary):hover:not(.is-pad-focus, .is-open) { background-color: var(--glass) !important; box-shadow: inset 0 0 0 1px var(--glass-edge), var(--shadow-edge-light) !important; }
/* Settings › Controller: the button diagram (FIXES #67). */
.cm svg { width: 100%; max-width: 980px; height: auto; display: block; margin: 0 auto; }
.cm .cm-body { fill: var(--glass-lift); stroke: var(--glass-edge); stroke-width: 2; }
.cm .cm-trig, .cm .cm-stick { fill: var(--glass-lift-strong); stroke: var(--glass-edge); stroke-width: 1.5; }
.cm .cm-key { fill: rgba(255, 255, 255, 0.10); stroke: var(--glass-edge); stroke-width: 1.5; }
.cm .cm-a { fill: #3c9b4f; } .cm .cm-b { fill: #c1443c; } .cm .cm-x { fill: #3a74c7; } .cm .cm-y { fill: #c8a23a; }
.cm .cm-glyph { fill: #ffffff; font: 700 13px/1 var(--font-text); text-anchor: middle; }
.cm .cm-line { stroke: var(--ink-muted); stroke-width: 1; fill: none; opacity: 0.6; }
.cm .cm-dot { fill: var(--accent); }
.cm .cm-text { fill: var(--ink); font: 500 13px/1 var(--font-text); }
.cm .cm-note { margin-top: 10px; font-size: 12px; line-height: 16px; }
/* System flyout: a temperature beside CPU / GPU (FIXES #73). */
.sys-temp { font-weight: 500; color: var(--ink-muted); }
/* Settings' section list: pointing at a section brightens it instead of a grey bar; the open one keeps the selected look. */
.se-list .b-item.is-focus:not(.is-selected) { box-shadow: var(--highlight-edge); }
.se-list .b-item:not(.is-selected) { color: var(--ink-muted); }
.se-list .b-item:not(.is-selected) .b-icon { transition: color var(--dur-move) var(--ease-standard); }
.se-list .b-item.is-focus:not(.is-selected), .se-list .b-item:hover:not(.is-selected) { color: var(--ink); }
.se-list .b-item.is-focus:not(.is-selected) .b-icon, .se-list .b-item:hover:not(.is-selected) .b-icon { color: var(--accent); }
/* The Terminal tab (FIXES #76). */
.term-page { flex: 1; min-height: 0; display: flex; }   /* laid out like the Server page: the panel fills the page area */
/* One outline: the glass panel itself carries the terminal's dark tint, so its edges and corners are the glass's own. */
.term-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 4px; padding: 12px; background-color: rgba(8, 10, 14, 0.62); --term-fg: #e6e9ef; --term-bg: #0d0f14; }
.term-head { display: flex; align-items: center; gap: 10px; padding: 0 8px 0 4px; min-height: 36px; }
.term-head b { font-size: 16px; }
.term-scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.term { position: relative; min-height: 100%; padding: 4px 4px; outline: none; font: 400 13px/18px 'Cascadia Mono', 'Cascadia Code', Consolas, monospace; color: var(--term-fg); white-space: pre; cursor: text; user-select: text; }
.term-line { height: 18px; }
.term-cursor { outline: 1px solid var(--term-fg); background: rgba(255, 255, 255, 0.85) !important; color: #0d0f14 !important; }
.term:not(:focus) .term-cursor { background: none !important; color: inherit !important; }
.term-measure { position: absolute; visibility: hidden; left: 0; top: 0; }
/* Wallpapers in their order (FIXES #78): dragged to where they should come; numbered while changing in order. */
.se-wall { cursor: grab; }
.se-wall .se-wall-n { position: absolute; left: 8px; bottom: 8px; min-width: 24px; height: 24px; padding: 0 6px; display: grid; place-items: center; border-radius: 12px; background: rgba(14, 14, 20, 0.62); font: 600 12px/1 var(--font-text); }
.se-wall.dragging { z-index: 3; cursor: grabbing; transition: none; box-shadow: var(--shadow-lift, 0 12px 32px rgba(0, 0, 0, 0.45)); opacity: 0.92; }
/* Background apps pinned to keep running (Nov 8): a pin beside them; one not running is dimmed and says so. */
.ov-bgrow .ov-bgpin { display: inline-flex; color: var(--accent); }
.ov-bgrow .ov-bgpin .b-icon { width: 14px; height: 14px; }
.ov-bgrow.is-off > img, .ov-bgrow.is-off > .b-icon { opacity: 0.5; }
.ov-bgrow .ov-bgoff { margin-left: auto; font-size: 12px; }
/* Bridge in the dock, always first (FIXES #88). */
.ov-bridge-app .ov-mark { width: 30px; height: 30px; }
.ov-bridge-app .ov-mark svg { width: 30px; height: 21px; }
/* An open app's still picture while a menu is over its card (Windows draws the live one above everything). */
.ov-thumb { position: relative; }
.ov-thumb .ov-snap { position: absolute; inset: 6px; width: calc(100% - 12px); height: calc(100% - 12px); object-fit: contain; border-radius: 8px; }
/* The browser's tab rows: the × of a tab that isn't current shows only while the pointer (or the highlight) is on it. */
.b-item:not(:hover):not(.is-focus) .sb-x { visibility: hidden; }
/* The top bar (decisions 145, 146): what's selected or open (the current tab, the Bridge mark on Home, an icon whose
   panel is open, Settings while it shows) has the selected look, the neon edge with the glow inside, and grows 1.04.
   Where the pointer or the D-pad is has the highlight edge with no glow inside, from the shared rules above. */
.b-topbar .b-btn.is-open, .b-topbar .b-tab.is-open { color: var(--ink); background: var(--selected); box-shadow: var(--selected-edge); transform: scale(var(--select-grow)); }
/* A highlighted field (decision 152): its border becomes the highlight's core line and the glow sits just outside it.
   Last, so it wins over each kind of field's own edge (on the wallpaper, in glass, on light glass). */
.b-field:hover:not(:has(input:disabled)), .b-field:has(input.is-pad-focus) { border-color: var(--highlight-line); box-shadow: var(--highlight-glow); }
.b-field.on-wall:hover:not(:has(input:disabled)), .b-field.on-wall:has(input.is-pad-focus) { box-shadow: var(--highlight-glow), var(--shadow-glass); }

/* ---- Bridge 2.0: packages (PLAN-2.0 item 21; boards in docs/mockups/2.0) ---- */
/* Window: an app's own glass window over the desktop. Kit draws the blur behind it (--blur-standalone); this is the
   luminosity layer, the edge and the float shadow, with the Window bar and the page inside. */
.b-window { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-4); border-radius: var(--radius); border: 1px solid var(--glass-edge);
  background: var(--glass-luminosity-dark); box-shadow: var(--shadow-edge-light), var(--shadow-float); }
.b-window.on-bright, .on-bright .b-window, [data-theme="light"] .b-window { background: var(--glass-luminosity-light); }
/* Window bar: the top bar of an app on its own. The app's mark and name, its own tools, a stretch to drag the window
   by, then Settings, a hairline, and Minimize, Maximize (Restore when maximised) and Close: all 32px quiet icon buttons. */
.b-topbar.b-winbar { grid-template-columns: auto 1fr auto; }
.b-winbar .b-logo { font: 500 14px/20px var(--font-display); letter-spacing: 0; text-transform: none; }
.b-winbar .drag { align-self: stretch; }
.b-winbar .sep { width: 1px; height: 20px; flex: none; background: var(--glass-edge); margin: 0 var(--space-1); }
/* Package icon: a package's mark in an inset tile. 40px in a row, 48px (.md) on a Store card, 52px (.lg) in a dialog,
   72px (.xl) on the Store's featured card. */
.b-pkg-icon { width: var(--size-control); height: var(--size-control); flex: none; display: grid; place-items: center; border-radius: var(--radius);
  background: var(--glass-inset); border: 1px solid var(--glass-edge); box-shadow: var(--shadow-edge-light); color: var(--ink); }
.b-pkg-icon.md { width: 48px; height: 48px; }
.b-pkg-icon.lg { width: var(--size-control-lg); height: var(--size-control-lg); }
.b-pkg-icon.lg .b-icon { width: 26px; height: 26px; }
.b-pkg-icon.xl { width: 72px; height: 72px; }
.b-pkg-icon.xl .b-icon { width: 32px; height: 32px; }
/* Permission list: what a package can do, in plain words: a label ("It can") and one 36px row per power, each with
   its icon. In the Add to Bridge dialog and under a package's row in Settings > Apps. */
.b-perms { padding: var(--space-2); display: flex; flex-direction: column; gap: 2px; border-radius: var(--radius); background: var(--glass-inset); border: 1px solid var(--glass-edge); }
.b-perms > .b-label { padding: var(--space-1) var(--space-2); }
.b-perms > .b-item { height: 36px; padding: 0 var(--space-2); cursor: default; }
/* Package row: a settings row for one installed package: its icon, name, a line of facts (version, publisher, what's
   waiting), then Update or Update Bridge, the Show in Bridge switch and More. Its permission list sits under it,
   lined up with the name. */
.b-srow.b-pkg > .b-pkg-icon + .txt b { font-weight: 600; }
.b-srow.b-pkg + .b-perms { margin: 0 var(--space-4) 6px 72px; }
/* Store card: one package in the Store: icon, name and publisher, two lines of what it is, then one full-width
   button (Install, Installed, Update) or its download progress in the button's place. */
.b-store-card { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); border-radius: var(--radius); background: var(--glass-inset);
  border: 1px solid var(--glass-edge); box-shadow: var(--shadow-edge-light); }
.b-store-card .head { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.b-store-card .head .txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.b-store-card .head .txt b { font-weight: 600; }
.b-store-card .desc { min-height: var(--size-control); color: var(--ink-muted); }
.b-store-card .progress { height: var(--size-control); display: flex; align-items: center; gap: var(--space-3); }
.b-store-card .progress .b-track { flex: 1; height: 4px; }
.b-store-card.featured { flex-direction: row; align-items: center; gap: var(--space-5); padding: var(--space-5); }
.b-store-card.featured .txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.b-store-card.featured > .b-btn { min-width: 120px; }

/* ---- Phone: a package's mobile UI in Bridge Mobile (PLAN-2.0 item 36a; the Mobile boards in docs/mockups/2.0) ---- */
/* The same components at phone sizes: one column, 16px from the screen's edges (and clear of the notch and the home
   bar), everything a finger presses at least 44px, and nothing that lights up under a pointer that isn't there. */
.b-phone { min-height: 100dvh; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--space-3); font-family: var(--font-text); color: var(--ink);
  padding: max(var(--space-4), env(safe-area-inset-top)) max(var(--space-4), env(safe-area-inset-right)) max(var(--space-4), env(safe-area-inset-bottom)) max(var(--space-4), env(safe-area-inset-left));
  -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
.b-phone .b-btn, .b-phone .b-field, .b-phone .b-seg > * { min-height: var(--size-touch); }
.b-phone .b-btn.sm { min-height: var(--size-touch); }
.b-phone .b-icon-btn { width: var(--size-touch); height: var(--size-touch); }
.b-phone .b-item { min-height: var(--size-touch); height: auto; }
.b-phone .b-field input { font-size: 16px; }   /* smaller text makes a phone zoom the page when the field is tapped */
/* The bar at the top: Back (to the app drawer), the app's name over the PC it is talking to, and one action. */
.b-phonebar { flex: none; height: var(--size-phone-bar); padding: 0 var(--space-2); display: flex; align-items: center; gap: var(--space-2); }
.b-phonebar .name { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.b-phonebar .name:first-child { padding-left: var(--space-2); }
.b-phonebar .name b { font: 600 17px/22px var(--font-display); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.b-phonebar .pc { display: flex; align-items: center; gap: 6px; font-size: 12px; line-height: 16px; color: var(--ink-muted); }
.b-phonebar .pc::before { content: ""; width: 7px; height: 7px; border-radius: var(--radius-round); background: var(--success); }
.b-phonebar .pc.away::before { background: var(--ink-faint); }
/* No hover on a phone: a finger leaves the last thing it touched "hovered", so the highlight edge is switched off
   there. What is selected, open or pressed keeps its own look. */
@media (hover: none) {
  .b-phone { --highlight-edge: 0 0 0 0 transparent; --highlight-glow: 0 0 0 0 transparent; --highlight-line: var(--glass-edge); }
}

/* ---- Money (Bridge Money: mockups 2.0/money). Money on a calendar and in categories. ------------------------------ */
/* Six category colours, in order: the accent, then pink, amber, coral, blue and grey (none is green: money in is green). A seventh category and on share grey. */
.b-money { --cat-1: var(--accent); --cat-2: #e0569a; --cat-3: var(--warning); --cat-4: #ff9a8a; --cat-5: #7fb2ff; --cat-6: #9aa3b5; }
.b-money-fig { font: 600 40px/44px var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.5px; white-space: nowrap; }
.b-money-fig.sm { font-size: 24px; line-height: 28px; }
.b-money-dot { width: 10px; height: 10px; border-radius: 3px; flex: none; background: var(--cat, var(--cat-6)); }
.b-money-stack { display: flex; gap: 3px; height: 12px; }
.b-money-stack > i { min-width: 4px; border-radius: var(--radius-round); background: var(--cat, var(--cat-6)); transition: flex-grow var(--dur-panel) var(--ease-standard); }
.b-money .b-track > i { background: var(--cat, var(--accent)); transition: width var(--dur-panel) var(--ease-standard); }
.b-money-donut { width: 180px; height: 180px; flex: none; border-radius: var(--radius-round); display: grid; place-items: center; background: var(--donut, var(--glass-inset)); }
.b-money-donut > div { width: 122px; height: 122px; border-radius: var(--radius-round); background: var(--wall-base); display: flex; flex-direction: column; align-items: center; justify-content: center; }
/* The calendar: seven equal columns. A day is brighter the more was spent on it (--heat, 0% to 40% of the accent). */
.b-money-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.b-money-cal > .b-label { padding: 0 var(--space-2); }
.b-money-day { min-height: 96px; min-width: 0; padding: var(--space-2); border-radius: var(--radius); display: flex; flex-direction: column; gap: 3px; cursor: pointer;
  background: color-mix(in srgb, var(--accent) var(--heat, 0%), var(--glass-inset)); transition: box-shadow var(--dur-move) var(--ease-standard), background var(--dur-move) var(--ease-standard); }
.b-money-day:hover, .b-money-day:focus-visible { box-shadow: var(--highlight-edge); outline: none; }
.b-money-day.is-today { box-shadow: var(--selected-edge); }
.b-money-day.is-out { opacity: 0.45; }
.b-money-day > .pills { margin-top: auto; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.b-money-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-2); }
.b-money-week > .b-money-day { min-height: 150px; padding: var(--space-3); }
/* A small pill on a day or a row: a bill (amber), payday (the accent), paid or saving (green). */
.b-money-pill { height: 20px; padding: 0 8px; border-radius: var(--radius-round); display: inline-block; max-width: 100%; box-sizing: border-box; font: 600 11px/20px var(--font-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: color-mix(in srgb, var(--tone, var(--ink-muted)) 22%, transparent); color: color-mix(in srgb, var(--tone, var(--ink-muted)) 55%, var(--ink)); }
.b-money-pill.bill { --tone: var(--warning); }
.b-money-pill.payday { --tone: var(--accent); }
.b-money-pill.paid, .b-money-pill.saving { --tone: var(--success); }
.b-money-icon { width: 36px; height: 36px; flex: none; border-radius: var(--radius-round); background: var(--glass-lift); display: grid; place-items: center; }
.b-money-keys { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
.b-money-keys > .b-btn { min-width: 0; height: var(--size-control-lg); padding: 0; font: 600 18px/1 var(--font-mono); }
/* On a phone: days are small squares with a dot for a bill or payday, and the four pages are a bar at the bottom. */
.b-phone .b-money-cal { gap: var(--space-1); }
.b-phone .b-money-day { min-height: var(--size-touch); padding: var(--space-1); align-items: center; gap: 0; }
.b-phone .b-money-day > .pills { flex-direction: row; justify-content: center; }
.b-money-pill.dot, .b-phone .b-money-day .b-money-pill { width: 6px; height: 6px; padding: 0; font-size: 0; background: var(--tone, var(--ink-muted)); }
.b-phone .b-money-fig { font-size: 32px; line-height: 36px; }
.b-money-tabs { position: sticky; bottom: var(--space-3); margin-top: auto; display: flex; gap: var(--space-2); align-items: center; }
.b-money-tabs > nav { flex: 1; min-width: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); padding: var(--space-1); }
.b-money-tabs > nav > button { all: unset; box-sizing: border-box; min-height: var(--size-control-lg); border-radius: var(--radius); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font: 500 11px/14px var(--font-text); color: var(--ink-muted); cursor: pointer; transition: background var(--dur-move) var(--ease-standard), color var(--dur-move) var(--ease-standard); }
.b-money-tabs > nav > button.is-selected { background: var(--selected); box-shadow: var(--selected-edge); color: var(--ink); }
.b-money-tabs > .b-icon-btn { width: var(--size-control-lg); height: var(--size-control-lg); border-radius: var(--radius-round); }
