/* static/studio/studio.css -- the new photographer interface: tokens, shell,
   shared components.

   STUDIO_UI_LOT1_2026_09_13 -- spec docs/inprogress/refonte-interface-photographe.md,
   sections 4 and 5. Ported from static/maquettes/studio-coquille-v2-2026-09-13.html.

   RULE: components consume tokens only. A colour written in a page is a
   defect (decision D6). Three theme states: light on :root, dark under the
   media query guarded by :root:not([data-theme="light"]), dark again under
   :root[data-theme="dark"]. The account preference is stamped on <html> by the
   Jinja shell; 'system' stamps nothing.

   Bump studio_routes.ASSET_V on every change. */

/* ============ Tokens ============ */
:root {
  --bg: #f3f3f7;
  --surface: #ffffff;
  --surface-2: #f8f8fb;
  --surface-3: #ededf2;
  --border: #e1e1ea;
  --border-soft: #ebebf1;
  --border-strong: #cfcfdb;
  --text: #16161c;
  --text-dim: #5f5f6d;
  --text-faint: #9393a1;
  --accent: #5b4fe3;
  --accent-ink: #4a3fd0;
  --accent-hover: #392fbd;  /* twice the step of --accent-ink, so the hover shows */
  --accent-soft: rgba(91, 79, 227, 0.10);
  --accent-line: rgba(91, 79, 227, 0.35);
  --on-accent: #ffffff;
  --success: #1f9a5a; --success-soft: #e3f5ea;
  /* "attention / en attente" -- sarcelle, decision D7 */
  --warn: #15858a;    --warn-soft: rgba(21, 133, 138, 0.12);
  --danger: #cc4141;  --danger-soft: #fbe9e9;
  --info: #2b6cc4;    --info-soft: #e6eefc;
  /* NOTIF_IMPORTANT_LOT1_2026_10_07 : « important » -- amber, apart from the
     red of an error and the violet of the accent. --on-imp is the text ON it. */
  --imp: #b86e00;     --imp-soft: #fff4e2; --imp-line: rgba(184,110,0,.38); --on-imp: #ffffff;
  --shadow: 0 1px 2px rgba(20,20,40,.05), 0 10px 30px rgba(20,20,40,.08);
  --shadow-pop: 0 12px 36px rgba(20,20,40,.18);
  --serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --sans: 'Inter', -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --tile-a: #d9d5f2; --tile-b: #cfd8ee; --tile-c: #e7d6dc; --tile-d: #d6e4dd; --tile-e: #e8dfcf; --tile-f: #d9dde4;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0a0a0c;
    --surface: #131318;
    --surface-2: #17171d;
    --surface-3: #1e1e26;
    --border: #25252e;
    --border-soft: #1d1d26;
    --border-strong: #35353f;
    --text: #ededf0;
    --text-dim: #8a8a96;
    --text-faint: #5a5a66;
    --accent: #7c6ff5;
    --accent-ink: #9a8ffa;
    --accent-hover: var(--accent-ink);
    --accent-soft: rgba(124, 111, 245, 0.14);
    --accent-line: rgba(124, 111, 245, 0.45);
    --on-accent: #ffffff;
    --success: #6fd49a; --success-soft: rgba(111,212,154,.14);
    --warn: #6fc8d4;    --warn-soft: rgba(111,200,212,.16);
    --danger: #f56f6f;  --danger-soft: rgba(245,111,111,.14);
    --info: #6fb6f5;    --info-soft: rgba(111,182,245,.14);
    --imp: #f0b35a;     --imp-soft: rgba(240,179,90,.13); --imp-line: rgba(240,179,90,.42); --on-imp: #241703;
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 10px 30px rgba(0,0,0,.35);
    --shadow-pop: 0 12px 36px rgba(0,0,0,.6);
    --tile-a: #2a2740; --tile-b: #222a3a; --tile-c: #35262c; --tile-d: #22302a; --tile-e: #342d22; --tile-f: #262930;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #0a0a0c;
  --surface: #131318;
  --surface-2: #17171d;
  --surface-3: #1e1e26;
  --border: #25252e;
  --border-soft: #1d1d26;
  --border-strong: #35353f;
  --text: #ededf0;
  --text-dim: #8a8a96;
  --text-faint: #5a5a66;
  --accent: #7c6ff5;
  --accent-ink: #9a8ffa;
  --accent-hover: var(--accent-ink);
  --accent-soft: rgba(124, 111, 245, 0.14);
  --accent-line: rgba(124, 111, 245, 0.45);
  --on-accent: #ffffff;
  --success: #6fd49a; --success-soft: rgba(111,212,154,.14);
  --warn: #6fc8d4;    --warn-soft: rgba(111,200,212,.16);
  --danger: #f56f6f;  --danger-soft: rgba(245,111,111,.14);
  --info: #6fb6f5;    --info-soft: rgba(111,182,245,.14);
  --imp: #f0b35a;     --imp-soft: rgba(240,179,90,.13); --imp-line: rgba(240,179,90,.42); --on-imp: #241703;
  --shadow: 0 1px 2px rgba(0,0,0,.4), 0 10px 30px rgba(0,0,0,.35);
  --shadow-pop: 0 12px 36px rgba(0,0,0,.6);
  --tile-a: #2a2740; --tile-b: #222a3a; --tile-c: #35262c; --tile-d: #22302a; --tile-e: #342d22; --tile-f: #262930;
  color-scheme: dark;
}

/* ============ Base ============ */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
[hidden] { display: none !important; }
svg.ic { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; flex: none; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; } }

/* Ascenseurs : fins, aux couleurs du thème (spec 4.5) */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: var(--text-faint); }
::-webkit-scrollbar-corner { background: transparent; }

/* ============ Shell ============ */
.app { position: relative; display: flex; height: 100vh; height: 100dvh; background: var(--bg); overflow: hidden; }
.app.no-anim .side, .app.no-anim .side * { transition: none !important; }

/* --- side --- */
.side {
  display: flex; flex-direction: column; flex: none;
  width: 248px; background: var(--surface); border-right: 1px solid var(--border-soft);
  transition: width .2s ease, transform .25s ease;
  z-index: 30;
}
.brand { display: flex; align-items: center; gap: 10px; height: 60px; padding: 0 10px 0 18px; border-bottom: 1px solid var(--border-soft); flex: none; }
.brand-link { display: flex; align-items: center; gap: 10px; text-decoration: none; min-width: 0; }
.brand .mark { width: 26px; height: 30px; flex: none; }
.brand .mark path { fill: var(--text); }
.brand .word { font-family: var(--serif); font-size: 22px; font-weight: 600; line-height: 1; white-space: nowrap; letter-spacing: .2px; }
.brand .word small { display: block; font-family: var(--serif); font-style: italic; font-weight: 500; font-size: 12px; color: var(--text-faint); letter-spacing: .4px; margin-top: 2px; }
.beta { display: inline-block; font-family: var(--sans); font-style: normal; font-size: 9.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); background: var(--accent-soft); border-radius: 5px; padding: 1px 5px; margin-left: 6px; vertical-align: 2px; }
.brand .collapse { margin-left: auto; border: none; background: transparent; color: var(--text-faint); width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; cursor: pointer; flex: none; }
.brand .collapse:hover { background: var(--surface-3); color: var(--text); }

.nav { flex: 1; overflow-y: auto; padding: 10px 10px 6px; }
.nav-group { margin-bottom: 8px; }
.nav-label { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--text-faint); font-weight: 600; padding: 10px 10px 4px; white-space: nowrap; }
.nav-item {
  display: flex; align-items: center; gap: 11px; height: 36px; padding: 0 10px; border-radius: 9px;
  color: var(--text-dim); text-decoration: none; font-size: 13.5px; font-weight: 500; white-space: nowrap;
  position: relative; cursor: pointer;
}
.nav-item:hover { background: var(--surface-3); color: var(--text); }
.nav-item[aria-current="page"] { background: var(--accent-soft); color: var(--accent-ink); }
.nav-item[aria-current="page"]::before { content: ''; position: absolute; left: -10px; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; background: var(--accent); }
.nav-item .txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.nav-item .ext { width: 13px; height: 13px; color: var(--text-faint); opacity: .7; }
.nav-item .badge { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; background: var(--accent); color: var(--on-accent); font-size: 11px; font-weight: 600; display: grid; place-items: center; font-variant-numeric: tabular-nums; }
.nav-item .badge.soft { background: var(--warn-soft); color: var(--warn); }
.nav-item .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--warn); }

.side-foot { border-top: 1px solid var(--border-soft); padding: 8px 10px; position: relative; flex: none; }
.me { display: flex; align-items: center; gap: 10px; width: 100%; padding: 6px 8px; border: none; background: transparent; border-radius: 10px; cursor: pointer; text-align: left; }
.me:hover { background: var(--surface-3); }
.avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-ink); border: 1px solid var(--accent-line); display: grid; place-items: center; font-size: 11px; font-weight: 600; flex: none; letter-spacing: .5px; }
.me .meta { min-width: 0; line-height: 1.25; }
.me .meta b { display: block; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me .meta small { display: block; font-size: 11.5px; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me .chev { margin-left: auto; color: var(--text-faint); }

.pop {
  position: absolute; left: 10px; right: 10px; bottom: calc(100% + 6px);
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-pop);
  padding: 6px; z-index: 50;
}
.pop .head { display: flex; align-items: center; gap: 10px; padding: 8px 8px 10px; border-bottom: 1px solid var(--border-soft); margin-bottom: 4px; }
.pop .head .meta { line-height: 1.25; min-width: 0; }
.pop .head b { display: block; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pop .head small { color: var(--text-faint); font-size: 11.5px; }
.pop a, .pop .row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; text-decoration: none; font-size: 13px; color: var(--text); cursor: pointer; }
.pop a:hover { background: var(--surface-3); }
.pop a .ext { width: 13px; height: 13px; color: var(--text-faint); margin-left: auto; }
.pop a .badge { margin-left: auto; font-size: 10.5px; font-weight: 600; background: var(--accent-soft); color: var(--accent-ink); padding: 2px 7px; border-radius: 10px; }
.pop .row.theme { cursor: default; justify-content: space-between; }
.pop .sep { height: 1px; background: var(--border-soft); margin: 4px 0; }
.pop a.danger { color: var(--danger); }

.seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 2px; }
.seg button { border: none; background: transparent; padding: 3px 8px; border-radius: 6px; cursor: pointer; color: var(--text-dim); font-size: 11.5px; font-weight: 500; }
.seg button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-ink); }

/* --- main --- */
.mainwrap { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; gap: 12px; height: 60px; padding: 0 20px 0 22px;
  border-bottom: 1px solid var(--border-soft); background: var(--bg); flex: none;
}
.burger { display: none; border: none; background: transparent; width: 36px; height: 36px; border-radius: 9px; place-items: center; color: var(--text); cursor: pointer; margin-left: -8px; }
.crumb { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-faint); min-width: 0; }
.crumb a { color: var(--text-faint); text-decoration: none; white-space: nowrap; }
.crumb a:hover { color: var(--text); }
.crumb a + a::before, .crumb a + span::before, .crumb span + span::before, .crumb span + a::before {
  content: ''; display: inline-block; width: 6px; height: 6px; border-right: 1.5px solid var(--border-strong); border-top: 1.5px solid var(--border-strong); transform: rotate(45deg); margin: 0 8px 1px 0; vertical-align: middle;
}
.crumb span { color: var(--text); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
/* DASHBOARD_HERO_2026_09_16, D5 : a real field, right-aligned next to the buttons on
   every page; the dashboard hides its crumb and lets the field take the left instead.
   Scoped to .topbar: the ported pages (galleries, clients, orders...) have a .search of
   their own, and the shell must not dress it. */
.topbar .search { position: relative; display: flex; align-items: center; gap: 9px; height: 38px; padding: 0 14px; margin: 0 0 0 auto; border: 1px solid var(--border); background: var(--surface); border-radius: 12px; color: var(--text-faint); font-size: 13px; cursor: text; flex: 0 1 380px; min-width: 140px; }
.topbar .search:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft); }
.topbar .search input { flex: 1; min-width: 0; border: 0; background: transparent; font: inherit; color: var(--text); outline: none; padding: 0; }
.topbar .search input::placeholder { color: var(--text-faint); }
.topbar .search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.top-right { margin-left: 0; }
.topbar .soon { position: absolute; top: calc(100% + 8px); left: 0; right: 0; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-pop); padding: 12px 14px; font-size: 13px; color: var(--text-dim); z-index: 40; cursor: default; display: none; }
.topbar .soon:not([hidden]) { display: block; }
.topbar .soon b { color: var(--text); font-weight: 600; display: block; margin-bottom: 2px; }
/* a small square icon before a card title or a KPI */
.hic { width: 28px; height: 28px; border-radius: 9px; background: var(--accent-soft); color: var(--accent-ink); display: inline-grid; place-items: center; flex: none; }
.hic svg.ic { width: 14px; height: 14px; }
.hic.success { background: var(--success-soft); color: var(--success); }
.hic.warn { background: var(--warn-soft); color: var(--warn); }
.hic.rose { background: var(--danger-soft); color: var(--danger); }
.card .ch h3 { display: flex; align-items: center; gap: 9px; }
.topbar .search kbd { font-family: var(--sans); font-size: 10.5px; border: 1px solid var(--border); border-radius: 5px; padding: 1px 5px; color: var(--text-faint); background: var(--surface-2); }
.iconbtn { border: 1px solid var(--border); background: var(--surface); width: 36px; height: 36px; border-radius: 9px; display: grid; place-items: center; color: var(--text-dim); cursor: pointer; position: relative; }
.iconbtn:hover { color: var(--text); border-color: var(--border-strong); }
.m-title { display: none; font-family: var(--serif); font-size: 21px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* STUDIO_UI_ALBUM_BAR_2026_09_16 : the top padding lives on .inner, not on the scroller --
   a sticky element (the album bar of the photos screen) sticks to the scrollport's
   padding edge, so 28px of padding here meant 28px of content scrolling past above it. */
.content { flex: 1; overflow-y: auto; padding: 0 36px 48px; }
/* Anchored LEFT (STUDIO_UI_FIX_2026_09_16): screens read from the top-left
   corner, and the pages ported with a `*` reset already sat left while the
   others floated to the centre. 1500px is the legacy .main width. */
/* the id selector is on purpose: a ported page's reset (#studioContent * { padding: 0 })
   outranks .content > .inner and would zero this padding */
.content > .inner, #studioContent > .inner { max-width: 1500px; margin: 0; padding-top: 28px; }

/* --- phone tab bar --- */
.tabbar { display: none; position: absolute; left: 0; right: 0; bottom: 0; height: 64px; background: var(--surface); border-top: 1px solid var(--border-soft); z-index: 20; padding: 6px 4px 8px; }
.tabbar a { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; text-decoration: none; color: var(--text-faint); font-size: 10.5px; font-weight: 500; border-radius: 10px; position: relative; }
.tabbar a[aria-current="page"] { color: var(--accent-ink); }
.tabbar a svg.ic { width: 22px; height: 22px; }
.tabbar .badge { position: absolute; top: 4px; left: calc(50% + 6px); min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--accent); color: var(--on-accent); font-size: 10px; font-weight: 600; display: grid; place-items: center; }
.backdrop { display: none; position: absolute; inset: 0; background: rgba(10,10,12,.45); z-index: 25; }

/* ============ Modes (spec 4.3) ============ */
.app[data-mode="rail"] .side { width: 64px; }
.app[data-mode="rail"] .brand { padding: 0; justify-content: center; }
.app[data-mode="rail"] .brand .word, .app[data-mode="rail"] .brand .collapse,
.app[data-mode="rail"] .nav-label, .app[data-mode="rail"] .nav-item .txt, .app[data-mode="rail"] .nav-item .ext,
.app[data-mode="rail"] .me .meta, .app[data-mode="rail"] .me .chev { display: none; }
.app[data-mode="rail"] .nav { padding: 10px 12px; }
.app[data-mode="rail"] .nav-group + .nav-group { border-top: 1px solid var(--border-soft); padding-top: 8px; }
.app[data-mode="rail"] .nav-item { justify-content: center; padding: 0; width: 40px; height: 40px; }
.app[data-mode="rail"] .nav-item::before { left: -12px; }
.app[data-mode="rail"] .nav-item .badge { position: absolute; top: 4px; right: 2px; margin: 0; min-width: 16px; height: 16px; font-size: 10px; padding: 0 4px; }
.app[data-mode="rail"] .nav-item .dot { position: absolute; top: 7px; right: 7px; margin: 0; }
.app[data-mode="rail"] .me { justify-content: center; padding: 6px 0; }
.app[data-mode="rail"] .pop { left: 8px; right: auto; width: 260px; }
.app[data-mode="rail"] .content { padding: 0 28px 48px; }

/* rail peek: the side is taken out of the flow in rail mode, so unfolding it
   over the content moves nothing; the main area keeps a 64px gutter. */
.app[data-mode="rail"] .side { position: absolute; top: 0; bottom: 0; left: 0; z-index: 35; }
.app[data-mode="rail"] .mainwrap { margin-left: 64px; }
.app[data-mode="rail"].peek .side { width: 248px; box-shadow: var(--shadow-pop); }
.app[data-mode="rail"].peek .brand { padding: 0 10px 0 18px; justify-content: flex-start; }
.app[data-mode="rail"].peek .brand .word, .app[data-mode="rail"].peek .brand .collapse,
.app[data-mode="rail"].peek .nav-label, .app[data-mode="rail"].peek .nav-item .txt, .app[data-mode="rail"].peek .nav-item .ext,
.app[data-mode="rail"].peek .me .meta, .app[data-mode="rail"].peek .me .chev { display: revert; }
.app[data-mode="rail"].peek .brand .collapse { display: grid; }
.app[data-mode="rail"].peek .nav { padding: 10px 10px 6px; }
.app[data-mode="rail"].peek .nav-group + .nav-group { border-top: none; padding-top: 0; }
.app[data-mode="rail"].peek .nav-item { justify-content: flex-start; padding: 0 10px; width: auto; height: 36px; }
.app[data-mode="rail"].peek .nav-item::before { left: -10px; }
.app[data-mode="rail"].peek .nav-item .badge { position: static; margin-left: auto; min-width: 20px; height: 20px; font-size: 11px; padding: 0 6px; }
.app[data-mode="rail"].peek .nav-item .dot { position: static; margin-left: auto; }
.app[data-mode="rail"].peek .me { justify-content: flex-start; padding: 6px 8px; }
.app[data-mode="rail"].peek .pop { left: 10px; right: 10px; width: auto; }
/* the labels appear once the width has grown, not truncated mid-transition */
@keyframes st-peek-in { from { opacity: 0; } to { opacity: 1; } }
.app[data-mode="rail"].peek .brand .word, .app[data-mode="rail"].peek .nav-label,
.app[data-mode="rail"].peek .nav-item .txt, .app[data-mode="rail"].peek .me .meta { animation: st-peek-in .15s .18s both; }

.app[data-mode="mobile"] .side { position: absolute; top: 0; bottom: 0; left: 0; width: 284px; transform: translateX(-100%); box-shadow: none; }
.app[data-mode="mobile"].drawer-open .side { transform: none; box-shadow: var(--shadow-pop); }
.app[data-mode="mobile"].drawer-open .backdrop { display: block; }
.app[data-mode="mobile"] .brand .collapse { display: none; }
.app[data-mode="mobile"] .topbar { height: 56px; padding: 0 12px 0 14px; }
.app[data-mode="mobile"] .burger { display: grid; }
.app[data-mode="mobile"] .crumb, .app[data-mode="mobile"] .topbar .search { display: none; }
.app[data-mode="mobile"] .m-title { display: block; }
.app[data-mode="mobile"] .content { padding: 0 16px 90px; }
.app[data-mode="mobile"] #studioContent > .inner { padding-top: 18px; }
.app[data-mode="mobile"] .tabbar { display: flex; }

/* ============ Shared components ============ */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 22px; flex-wrap: wrap; }
.page-head h1 { font-family: var(--serif); font-weight: 600; font-size: 32px; line-height: 1.05; margin: 0; letter-spacing: .2px; text-wrap: balance; }
.page-head .sub { color: var(--text-dim); font-size: 13px; margin-top: 6px; }
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
.btn { display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: 9px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); font-size: 13px; font-weight: 500; cursor: pointer; text-decoration: none; white-space: nowrap; }
.btn:hover { background: var(--surface-3); }
.btn:disabled { opacity: .6; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.primary:hover { filter: brightness(1.06); background: var(--accent); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--text-dim); }
.btn.ghost:hover { background: var(--surface-3); color: var(--text); }
.btn.danger { color: var(--danger); border-color: var(--danger); }
.btn.sm { height: 30px; padding: 0 10px; font-size: 12.5px; }
.btn svg.ic { width: 16px; height: 16px; }

.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 22px; }
.kpi { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 12px; padding: 16px 18px; min-width: 0; }
.kpi .l { font-size: 12px; color: var(--text-dim); display: flex; align-items: center; gap: 6px; }
.kpi .n { font-family: var(--serif); font-size: 34px; font-weight: 600; line-height: 1.1; margin-top: 6px; font-variant-numeric: tabular-nums; }
.kpi .n small { font-size: 16px; color: var(--text-faint); font-family: var(--sans); font-weight: 500; margin-left: 4px; }
.kpi .d { font-size: 12px; margin-top: 4px; color: var(--text-faint); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kpi .d.up { color: var(--success); } .kpi .d.warn { color: var(--warn); }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 22px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 22px; }
.card { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 12px; min-width: 0; }
.card .ch { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 18px 0; }
.card .ch h3 { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .02em; }
.card .ch a { font-size: 12.5px; color: var(--accent-ink); text-decoration: none; }
.card .cb { padding: 12px 18px 16px; }

.list { display: flex; flex-direction: column; }
.list .li { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-soft); font-size: 13px; text-decoration: none; color: inherit; }
.list .li:last-child { border-bottom: none; }
.list a.li:hover .t b { color: var(--accent-ink); }
.list .li .ico { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; background: var(--surface-3); color: var(--text-dim); flex: none; }
.list .li .ico svg.ic { width: 15px; height: 15px; }
.list .li .t { flex: 1; min-width: 0; }
.list .li .t b { font-weight: 500; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list .li .t small { display: block; color: var(--text-faint); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list .li time, .list .li .r { color: var(--text-faint); font-size: 12px; white-space: nowrap; font-variant-numeric: tabular-nums; text-align: right; }
.list .li .r b { display: block; color: var(--text); font-weight: 600; font-size: 13px; }

.pill { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px; border-radius: 11px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill.ok { background: var(--success-soft); color: var(--success); }
.pill.off { background: var(--surface-3); color: var(--text-dim); }
.pill.warn { background: var(--warn-soft); color: var(--warn); }
.pill.info { background: var(--info-soft); color: var(--info); }
.pill.danger { background: var(--danger-soft); color: var(--danger); }
.pill.up { background: var(--success-soft); color: var(--success); } .pill.down { background: var(--danger-soft); color: var(--danger); }
.pill.plain::before { display: none; }

.toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
.toolbar .field { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface); color: var(--text-faint); font-size: 13px; flex: 1 1 220px; max-width: 320px; }
.toolbar .field input { border: none; background: transparent; outline: none; flex: 1; min-width: 0; font: inherit; color: var(--text); }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { height: 30px; padding: 0 12px; border-radius: 15px; border: 1px solid var(--border); background: var(--surface); font-size: 12.5px; font-weight: 500; color: var(--text-dim); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; text-decoration: none; }
.chip[aria-pressed="true"] { background: var(--text); color: var(--bg); border-color: var(--text); }
.chip small { color: inherit; opacity: .7; font-variant-numeric: tabular-nums; }

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border-soft); margin-bottom: 22px; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs a { padding: 10px 14px; font-size: 13.5px; font-weight: 500; color: var(--text-dim); text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; display: inline-flex; align-items: center; gap: 7px; }
.tabs a:hover { color: var(--text); }
.tabs a[aria-current="page"] { color: var(--text); border-bottom-color: var(--accent); }
.tabs a .n { font-size: 11px; color: var(--text-faint); background: var(--surface-3); border-radius: 9px; padding: 1px 6px; font-variant-numeric: tabular-nums; }
.tabs a[aria-current="page"] .n { background: var(--accent-soft); color: var(--accent-ink); }

.table-wrap { overflow-x: auto; border: 1px solid var(--border-soft); border-radius: 12px; background: var(--surface); }
table.tbl { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 640px; }
.tbl th { text-align: left; font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-faint); font-weight: 600; padding: 12px 16px; border-bottom: 1px solid var(--border-soft); white-space: nowrap; }
.tbl td { padding: 13px 16px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; white-space: nowrap; }
.tbl tr:last-child td { border-bottom: none; }
.tbl tbody tr.link { cursor: pointer; }
.tbl tbody tr.link:hover td { background: var(--surface-2); }
.tbl td.num, .tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.muted { color: var(--text-faint); }
.ref { font-family: var(--mono); font-size: 12px; color: var(--text-dim); }

.field-b label { display: block; font-size: 12px; font-weight: 600; color: var(--text-dim); margin-bottom: 6px; }
.field-b .in, .field-b input, .field-b select, .field-b textarea { width: 100%; min-height: 38px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface-2); padding: 8px 12px; font: inherit; font-size: 13.5px; color: var(--text); }
.field-b input:focus, .field-b select:focus, .field-b textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.field-b input::placeholder, .field-b textarea::placeholder { color: var(--text-faint); }
.field-b .hint { font-size: 12px; color: var(--text-faint); margin-top: 6px; }

.callout { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border-radius: 10px; background: var(--accent-soft); border: 1px solid var(--accent-line); font-size: 13px; margin-bottom: 18px; }
.callout svg.ic { color: var(--accent-ink); margin-top: 1px; }
.callout.warn { background: var(--warn-soft); border-color: var(--warn); } .callout.warn svg.ic { color: var(--warn); }
.callout.danger { background: var(--danger-soft); border-color: var(--danger); } .callout.danger svg.ic { color: var(--danger); }
.callout b { font-weight: 600; }

.empty { border: 1px dashed var(--border-strong); border-radius: 12px; padding: 22px; color: var(--text-dim); font-size: 13px; background: var(--surface-2); text-align: center; }

.greet h1 { font-family: var(--serif); font-size: 34px; font-weight: 600; margin: 0; line-height: 1.1; }
.greet p { margin: 6px 0 0; color: var(--text-dim); font-size: 13px; }

/* ============ Réactif intérieur (par mode, pas par fenêtre) ============ */
.app[data-mode="rail"] .kpis { grid-template-columns: repeat(2, 1fr); }
.app[data-mode="rail"] .grid-3 { grid-template-columns: 1fr 1fr; }
.app[data-mode="mobile"] .kpis { grid-template-columns: repeat(2, 1fr); gap: 10px; }
.app[data-mode="mobile"] .kpi { padding: 12px 14px; }
.app[data-mode="mobile"] .kpi .n { font-size: 28px; }
.app[data-mode="mobile"] .grid-2, .app[data-mode="mobile"] .grid-3 { grid-template-columns: 1fr; }
.app[data-mode="mobile"] .page-head h1 { font-size: 26px; }
.app[data-mode="mobile"] .page-head { margin-bottom: 16px; }
.app[data-mode="mobile"] .page-head .actions .btn:not(.primary) { display: none; }
.app[data-mode="mobile"] .toolbar .field { flex-basis: 100%; max-width: none; }
.app[data-mode="mobile"] .greet h1 { font-size: 26px; }

/* ============ Legacy compat (STUDIO_UI_LOT2_2026_09_13) ============
   Pages ported from static/ by tools/studio_port_page.py lost their :root block
   and keep using the old token names: aliased here to the studio tokens, so a
   ported page follows the theme without a rewrite. Literal colours get a light
   and a dark value like every other token. */
:root {
  --bg-card: var(--surface); --bg-card-hover: var(--surface-2); --bg-input: var(--surface-2);
  --accent-glow: var(--accent-line); --green: var(--success); --text-muted: var(--text-dim);
  --warning: var(--warn); --amber: var(--warn); --red: var(--danger); --tile-fit: contain;
  --gold: #b07a2a; --pink: #d0457f; --teal: #15858a;
  /* STUDIO_JETONS_MANQUANTS_2026_09_25 : five old names no alias carried. The
     ported pages used them WITHOUT a fallback, so the declaration was dropped:
     .btn-primary:hover lost its background, and in the light theme the white
     label sat on white -- the button vanished under the pointer (« Régénérer »,
     Paramètres > Uploader; six screens use --accent-hover). Old values: a
     deeper shade for the two hovers (--accent-hover lives with each theme,
     above), --text-subtle was --text-faint. */
  --red-hover: color-mix(in srgb, var(--danger) 82%, #000);
  --red-soft: var(--danger-soft);
  --green-soft: var(--success-soft);
  --text-subtle: var(--text-faint);
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --gold: #d8a868; --pink: #f56f9c; --teal: #6fc8d4; } }
:root[data-theme="dark"] { --gold: #d8a868; --pink: #f56f9c; --teal: #6fc8d4; }

/* the ported page's <main class="main"> -- its box is the shell's now */
.legacy-main { display: block; }
/* gallery tab strip rendered by the shell (decision D9). Its own class: a
   ported page may style `.tabs` for itself, this strip must not follow. */
#studioContent .st-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border-soft); margin: 0 0 20px; padding: 0; overflow-x: auto; scrollbar-width: none; }
#studioContent .st-tabs::-webkit-scrollbar { display: none; }
#studioContent .st-tabs a { padding: 10px 14px; font-size: 13.5px; font-weight: 500; color: var(--text-dim); text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; display: inline-flex; align-items: center; gap: 7px; background: none; }
#studioContent .st-tabs a:hover { color: var(--text); }
#studioContent .st-tabs a[aria-current="page"] { color: var(--text); border-bottom-color: var(--accent); }
/* PURGE_PURGED_GATE_2026_10_03 : the banner of a purged gallery, under the tabs. */
#studioContent .st-purged { margin: -6px 0 20px; padding: 12px 16px; border-radius: 10px; background: var(--danger-soft, #fbe9e9); color: var(--danger, #cc4141); font-size: 13.5px; line-height: 1.45; }
.app[data-mode="mobile"] #studioContent .st-tabs { margin: 0 -16px 16px; padding: 0 16px; }
/* ONGLETS_PLUS_2026_09_26 -- spec onglet-partage-galerie section 5. With JS the
   strip stops scrolling: what does not fit goes into « Plus ». Without JS the
   rules above keep the horizontal scroll. The current tab is never folded. */
#studioContent .st-tabs.is-foldable { overflow: visible; position: relative; flex-wrap: nowrap; }
#studioContent .st-tabs a[hidden] { display: none; }
#studioContent .st-tabs .st-more { position: relative; flex: none; margin-left: auto; display: flex; }
#studioContent .st-tabs .st-more[hidden] { display: none; }
#studioContent .st-tabs .st-more > button { display: inline-flex; align-items: center; gap: 5px; padding: 10px 12px; font: inherit; font-size: 13.5px; font-weight: 500; color: var(--text-dim); background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; white-space: nowrap; }
#studioContent .st-tabs .st-more > button:hover,
#studioContent .st-tabs .st-more > button[aria-expanded="true"] { color: var(--text); }
#studioContent .st-tabs .st-more > button svg.ic { width: 14px; height: 14px; transform: rotate(90deg); transition: transform .15s; }
#studioContent .st-tabs .st-more > button[aria-expanded="true"] svg.ic { transform: rotate(-90deg); }
#studioContent .st-tabs .st-menu { position: absolute; right: 0; top: calc(100% + 6px); min-width: 190px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-pop); padding: 6px; z-index: 50; display: flex; flex-direction: column; }
#studioContent .st-tabs .st-menu[hidden] { display: none; }
#studioContent .st-tabs .st-menu a { display: block; padding: 9px 12px; margin: 0; border: none; border-radius: 8px; font-size: 13.5px; font-weight: 500; color: var(--text-dim); }
#studioContent .st-tabs .st-menu a:hover,
#studioContent .st-tabs .st-menu a:focus-visible { background: var(--surface-3); color: var(--text); outline: none; }

/* --- notifications (PAYOUTS_LOT_C_2026_09_18, spec reversements § 5.5) --- */
.notif-wrap { position: relative; }
.iconbtn .dot { position: absolute; top: 6px; right: 6px; width: 9px; height: 9px; border-radius: 50%; background: var(--danger); border: 2px solid var(--surface); }
.iconbtn .dot[hidden] { display: none; }
.notifs { position: absolute; right: 0; top: calc(100% + 8px); width: 380px; max-width: calc(100vw - 24px); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-pop); z-index: 60; overflow: hidden; }
.notifs[hidden] { display: none; }
.notifs .head { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--border-soft); font-size: 13px; }
.notifs .head button { border: none; background: transparent; color: var(--accent-ink); font: inherit; font-size: 12px; cursor: pointer; padding: 2px 4px; }
.notifs .head button:hover { text-decoration: underline; }
.notifs .list { max-height: min(60vh, 480px); overflow-y: auto; }
.notifs .item { display: block; width: 100%; text-align: left; padding: 10px 14px 10px 26px; border: none; border-bottom: 1px solid var(--border-soft); background: transparent; font: inherit; color: var(--text); cursor: pointer; position: relative; text-decoration: none; }
.notifs .item:last-child { border-bottom: none; }
.notifs .item:hover { background: var(--surface-3); }
.notifs .item.unread::before { content: ''; position: absolute; left: 11px; top: 16px; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.notifs .item b { display: block; font-size: 13px; font-weight: 600; line-height: 1.3; }
.notifs .item.read b { font-weight: 500; color: var(--text-dim); }
.notifs .item p { margin: 3px 0 0; font-size: 12.5px; color: var(--text-dim); line-height: 1.4; }
.notifs .item small { display: block; margin-top: 4px; font-size: 11px; color: var(--text-faint); }
.notifs .empty { padding: 26px 14px; text-align: center; color: var(--text-faint); font-size: 13px; }
.app[data-mode="mobile"] .notifs { position: fixed; left: 12px; right: 12px; top: 64px; width: auto; }

/* --- important notifications (NOTIF_IMPORTANT_LOT1_2026_10_07, spec
   notifications-importantes, option D) : the amber bell with a count, the
   « À traiter » section, the bubble under the bell, the amber menu badge. --- */
.iconbtn.has-imp { color: var(--imp); border-color: var(--imp-line); background: var(--imp-soft); }
.iconbtn .count { position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--imp); color: var(--on-imp); font-size: 10.5px; font-weight: 700; display: grid; place-items: center; border: 2px solid var(--bg); line-height: 1; }
.iconbtn .count[hidden] { display: none; }
.badge.imp { background: var(--imp); color: var(--on-imp); }
.btn.imp { background: var(--imp); border-color: var(--imp); color: var(--on-imp); }
.btn.imp:hover { filter: brightness(1.06); background: var(--imp); }
.notifs .sec { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--text-faint); font-weight: 600; padding: 10px 14px 4px; }
.notifs .sec.imp { color: var(--imp); }
.notifs .item.imp { background: var(--imp-soft); border-left: 3px solid var(--imp); padding-left: 44px; cursor: default; }
.notifs .item.imp::before { display: none; }
.notifs .item.imp .ii { position: absolute; left: 14px; top: 11px; width: 22px; height: 22px; border-radius: 50%; background: var(--imp); color: var(--on-imp); display: grid; place-items: center; font-size: 13px; font-weight: 700; }
.notifs .item.imp .tag { display: block; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--imp); margin-bottom: 1px; }
.notifs .item.imp .acts { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.notifs .item.imp.done { background: transparent; border-left-color: var(--border-strong); cursor: pointer; }
.notifs .item.imp.done .ii { background: var(--surface-3); color: var(--text-faint); }
.notifs .item.imp.done .tag { color: var(--text-faint); }
.notifs .item.imp.done b { color: var(--text-dim); font-weight: 500; }
.bubble { position: absolute; right: 0; top: calc(100% + 10px); width: 360px; max-width: calc(100vw - 24px); background: var(--surface); border: 1px solid var(--imp-line); border-radius: 14px; box-shadow: var(--shadow-pop); z-index: 59; padding: 14px 16px; animation: bubble-in .25s ease-out; }
.bubble[hidden] { display: none; }
.bubble::before { content: ''; position: absolute; top: -7px; right: 13px; width: 12px; height: 12px; background: var(--surface); border-left: 1px solid var(--imp-line); border-top: 1px solid var(--imp-line); transform: rotate(45deg); }
.bubble .bh { display: flex; gap: 10px; align-items: flex-start; padding-right: 18px; }
.bubble .ii { width: 28px; height: 28px; border-radius: 50%; background: var(--imp); color: var(--on-imp); display: grid; place-items: center; flex: none; font-weight: 700; }
.bubble .tag { display: block; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--imp); }
.bubble b { display: block; font-size: 14px; line-height: 1.3; }
.bubble p { margin: 6px 0 0; font-size: 13px; color: var(--text-dim); line-height: 1.45; }
.bubble .acts { display: flex; gap: 8px; margin-top: 12px; align-items: center; flex-wrap: wrap; }
.bubble .more { margin-left: auto; border: 0; background: transparent; color: var(--text-faint); font: inherit; font-size: 12px; cursor: pointer; padding: 0; }
.bubble .more:hover { color: var(--text); text-decoration: underline; }
.bubble .bx { position: absolute; top: 8px; right: 8px; border: 0; background: transparent; color: var(--text-faint); font-size: 17px; line-height: 1; cursor: pointer; width: 26px; height: 26px; border-radius: 6px; }
.bubble .bx:hover { background: var(--surface-3); color: var(--text); }
@keyframes bubble-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .bubble { animation: none; } }
/* phone : a sheet from the bottom, big buttons, above the tab bar */
.app[data-mode="mobile"] .bubble { position: fixed; left: 0; right: 0; top: auto; bottom: 0; width: auto; max-width: none; border-radius: 18px 18px 0 0; border-width: 3px 0 0; border-top-color: var(--imp); padding: 18px 18px 26px; z-index: 80; }
.app[data-mode="mobile"] .bubble::before { display: none; }
.app[data-mode="mobile"] .bubble .acts { flex-direction: column; align-items: stretch; }
.app[data-mode="mobile"] .bubble .acts .btn { height: 42px; justify-content: center; font-size: 14px; }
.app[data-mode="mobile"] .bubble .more { margin: 4px auto 0; }

/* STORAGE_ESTIMATE_2026_09_29 : .info-tip, an "i" that opens a short bubble.
   A real <button> (focusable, tappable) carrying aria-describedby to its
   bubble; opens on hover, on keyboard focus and on tap (.is-open, set by the
   page), closes on Escape. The id prefix keeps a ported page's reset
   (#studioContent * { padding: 0 }) from flattening it. The bubble is anchored
   on the RIGHT edge of the button, so a tip at the right of the screen stays
   inside it. */
#studioContent .info-tip { position: relative; display: inline-flex; align-items: center; vertical-align: middle; }
#studioContent .info-tip > button { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; padding: 0; margin: 0; border: 0; border-radius: 50%; background: transparent; color: var(--text-faint); cursor: help; font: inherit; }
#studioContent .info-tip > button:hover, #studioContent .info-tip > button:focus-visible, #studioContent .info-tip.is-open > button { color: var(--accent-ink); }
#studioContent .info-tip > button:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 1px; }
#studioContent .info-tip > button .ic { width: 15px; height: 15px; }
#studioContent .info-tip .tip { position: absolute; right: -6px; bottom: calc(100% + 8px); z-index: 30; width: max-content; max-width: min(260px, 70vw); padding: 9px 11px; border-radius: 8px; background: var(--surface); color: var(--text); border: 1px solid var(--border); box-shadow: var(--shadow-pop); font-size: 12px; line-height: 1.45; font-weight: 400; text-align: left; white-space: normal; opacity: 0; visibility: hidden; transform: translateY(4px); transition: opacity .15s, transform .15s, visibility .15s; pointer-events: none; }
#studioContent .info-tip .tip::after { content: ""; position: absolute; right: 10px; top: 100%; border: 6px solid transparent; border-top-color: var(--border); }
#studioContent .info-tip:hover .tip, #studioContent .info-tip > button:focus-visible + .tip, #studioContent .info-tip.is-open .tip { opacity: 1; visibility: visible; transform: none; }
/* Escape wins over hover and focus until the pointer or the focus leaves. */
#studioContent .info-tip.is-closed .tip { opacity: 0; visibility: hidden; transform: translateY(4px); }
