/* ==========================================================================
   PitoReel Creative Studio - shared stylesheet for EVERY studio page.
   Modelled on YouTube Studio: light surface, left rail, one content column.

   THE ARC STAYS DARK. Only the Studio is light. Two products, two looks.

   Every colour is a token declared once here. Eleven pages hand-writing their
   own greys is how eleven pages drift apart.
   ========================================================================== */

:root {
  --bg:        #f9f9f9;   /* page                        */
  --surface:   #ffffff;   /* cards, rail, top bar        */
  --surface-2: #f2f2f2;   /* hover, inert fills          */
  --line:      #e5e5e5;   /* borders                     */
  --text:      #0f0f0f;   /* primary                     */
  --text-2:    #606060;   /* secondary - 5.9:1 on white  */
  /* Was #909090 and the comment said "large text only" - but it is used on 12px
     labels (the sidebar group headings BROWSE PITOREEL / YOUR STUDIO, the analytics
     stat captions, the duration cell), which is 3.19:1 and under AA. A token whose
     safe usage is narrower than its actual usage is a bug waiting to be found, so
     the token is darkened rather than hunting every call site. */
  --text-3:    #6e6e6e;   /* tertiary - 4.9:1 on white, safe at 12px */
  --accent:    #065fd4;   /* links, active state         */
  --accent-bg: #e5efff;   /* active rail item            */
  --gold:      #b98a00;   /* PitoReel accent, AA on white*/
  --gold-bg:   #fdf6e3;
  --danger:    #c5221f;
  --ok:        #128a3a;
  --rail-w:    240px;
  --rail-w-sm: 72px;
  --top-h:     56px;
  --radius:    12px;
  --shadow:    0 1px 2px rgba(0,0,0,.06), 0 2px 10px rgba(0,0,0,.04);
  color-scheme: light;
}

/* ==========================================================================
   DARK THEME - opt in, chosen by the creator, remembered per browser.
   Set by studio-shell.js as data-theme="dark" on <html>.

   It overrides ONLY the tokens. Every rule below reads them, so nothing else in
   this file needs a dark variant - which is the whole reason the palette is
   tokenised. Eleven pages with their own greys could never have done this.

   Contrast checked, because a dark theme is where accessibility usually breaks:
     --text-2 #aaaaaa on --surface #212121  = 7.0:1
     --accent #7cacf8 on --surface #212121  = 7.4:1
     --gold   #f0c040 on --surface #212121  = 10.0:1
   All comfortably past AA.
   ========================================================================== */
:root[data-theme="dark"] {
  --bg:        #0f0f0f;
  --surface:   #212121;
  --surface-2: #303030;
  --line:      #3f3f3f;
  --text:      #f1f1f1;
  --text-2:    #aaaaaa;
  --text-3:    #808080;
  --accent:    #7cacf8;
  --accent-bg: #263243;
  --gold:      #f0c040;
  --gold-bg:   #33291a;
  --danger:    #f28b82;
  --ok:        #6dd58c;
  --shadow:    0 1px 2px rgba(0,0,0,.5), 0 2px 10px rgba(0,0,0,.35);
  color-scheme: dark;
}

/* THE HARDCODED HEX VALUES BELOW THE TOKEN BLOCK, and only those. Seventeen rules
   carry a literal colour because they are tints and shades rather than palette
   entries. Each one is restated here for dark; anything reading a token needs no
   dark variant at all, which is the point of tokenising the palette. */
:root[data-theme="dark"] .st-avatar,
:root[data-theme="dark"] .st-chan-pic { background: var(--surface-2); }
:root[data-theme="dark"] .st-search input:focus { border-color: #5f5f5f; }
:root[data-theme="dark"] .st-badge { color: #0f0f0f; }
:root[data-theme="dark"] .st-btn-primary { background: var(--text); color: #0f0f0f; border-color: var(--text); }
:root[data-theme="dark"] .st-btn-primary:hover { background: #ffffff; }
:root[data-theme="dark"] .st-btn-accent { color: #0f0f0f; }
:root[data-theme="dark"] .st-btn-accent:hover { background: #a3c6fb; }
:root[data-theme="dark"] .st-btn-danger { border-color: #6b2b28; }
:root[data-theme="dark"] .st-btn-danger:hover { background: #3a1f1e; }
:root[data-theme="dark"] .st-table tr:hover td { background: #2a2a2a; }
:root[data-theme="dark"] .st-note.warn { border-color: #5c4a1e; color: #f0d48a; }
:root[data-theme="dark"] .st-note.err { background: #3a1f1e; border-color: #6b2b28; color: #f6b6b2; }
:root[data-theme="dark"] .st-note.ok { background: #16301f; border-color: #2a5c3a; color: #a8e6bd; }
:root[data-theme="dark"] .st-chip.ok { background: #16301f; }
:root[data-theme="dark"] .st-chip.err { background: #3a1f1e; }

/* A success note, so no page has to inline a green. Four of them did, and an inlined
   colour cannot follow a theme. */
.st-note.ok { background: #e6f4ea; border-color: #b7e1c1; color: #0d652d; }

/* ==========================================================================
   THE VIDEO EDITOR DIALOG.

   A FLEX COLUMN, not a scrolling box with a sticky player. A scroll container's
   PADDING is scrolled-through space, so a `position: sticky` video lets form
   fields slide past behind it - which is exactly what the first attempt did.
   Nothing can pass behind a flex sibling, so the video is genuinely static with
   no sticky hack at all.

   `min-height: 0` on the scrolling children is load-bearing: without it a flex
   child refuses to shrink below its content and the sheet grows past the screen.
   ========================================================================== */
.st-sheet.ed-sheet {
  max-width: 1040px;
  width: 100%;
  max-height: 94vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.st-sheet.ed-sheet .st-sheet-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
}
.ed-cols { display: flex; flex: 1; min-height: 0; overflow: hidden; gap: 22px; width: 100%; }
.ed-media {
  flex: 0 0 46%;
  max-width: 520px;
  height: 100%;
  min-height: 0;
  overflow-y: auto;
  padding-right: 4px;
}
.ed-body { flex: 1; min-width: 0; height: 100%; min-height: 0; overflow-y: auto; padding-right: 4px; }
.ed-media video, .ed-media img { max-height: 38vh; }

/* ==========================================================================
   THE UPLOAD DIALOG. Videos and pictures, up to ten, each with its own details.
   ========================================================================== */
/* MAXIMISED, because the whole form has to be visible.
   It was 780px - NARROWER than the 960px default - which is what made this dialog feel
   cramped and forced the genre list to scroll inside itself. It now uses nearly the whole
   viewport in both directions, so the form gets the room it needs instead of being folded
   into two nested scrollbars. */
/* The backdrop contributes 20px of padding on each side, so the sheet is always 40px
   narrower and shorter than the window. max-width is set high enough that the padding,
   not the cap, is what limits it on any ordinary screen - the cap only exists so the form
   does not stretch to absurd line lengths on an ultrawide monitor. */
.st-sheet.up-sheet {
  max-width: 1600px;
  width: 100%;
  height: calc(100vh - 40px);
  max-height: calc(100vh - 40px);
}
/* On a phone it is a FULL-SCREEN sheet. A rounded card floating in a grey border wastes
   the only screen space there is, and the backdrop padding has to be cancelled too or the
   sheet is stuck 40px short of the edges - which is exactly what it was. */
@media (max-width: 700px) {
  .st-backdrop.up-backdrop { padding: 0; }
  .st-sheet.up-sheet {
    width: 100%; max-width: 100%;
    height: 100vh; max-height: 100vh;
    border-radius: 0;
  }
}

.up-drop {
  border: 2px dashed var(--line);
  border-radius: 12px;
  padding: 40px 24px;
  text-align: center;
  cursor: pointer;
  color: var(--text-2);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  background: var(--surface);
}
.up-drop:hover, .up-drop.over { border-color: var(--accent); background: var(--accent-bg); }
.up-drop.over { border-style: solid; }
.up-ico { color: var(--text-3); margin-bottom: 4px; }
.up-title { color: var(--text); font-size: 15px; font-weight: 600; }
/* The primary action. Sized so it is unmistakably the thing to press.
   TWO classes deliberately: this block sits ABOVE the .st-btn definition in this
   file, so a single .up-pick has equal specificity and LOSES on order - the button
   snapped back to 36px and 101px wide. .st-btn.up-pick wins wherever it sits. */
.st-btn.up-pick {
  margin: 10px 0 4px;
  min-height: 46px; padding: 0 32px;
  font-size: 14.5px; font-weight: 600;
}
.st-btn.up-pick:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.up-hint { font-size: 12.5px; color: var(--text-2); }

.up-list { margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
.up-item { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.up-item-head {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; cursor: pointer; background: var(--surface-2);
  min-height: 44px;
}
.up-item-name {
  flex: 1; min-width: 0; font-weight: 500; font-size: 13.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.up-item-meta { font-size: 12px; color: var(--text-2); flex-shrink: 0; }
.up-item-body { padding: 14px 12px; }
/* NO INNER SCROLLBAR. This used to be max-height:132px with overflow-y:auto, which put a
   SECOND scrollbar inside a dialog that already scrolls - the recurring two-scrollbar
   defect on this platform. A dialog gets ONE scroll region: its own body.
   With the wider sheet the 27 genres wrap into a few rows and simply fit. */
.up-genres { display: flex; flex-wrap: wrap; gap: 6px 16px; }

/* ---------------------------------------------------------------- Analyze Video
   Offered at upload time, and it is the one paid feature in this dialog, so it is
   visually separated from the free fields rather than sitting among them as if it
   were just another checkbox. */
.up-analyze {
  border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 14px; background: var(--surface-2);
  margin-bottom: 20px;
}
.up-analyze-row { display: flex; align-items: flex-start; gap: 10px; min-height: 44px; }
.up-analyze-row input[type=checkbox] { margin-top: 3px; width: 18px; height: 18px; flex-shrink: 0; }
/* display:block IS REQUIRED on both of these. They are <span>s, so without it the title, the
   price tag and the description all run together on one line - which is what produced
   "Analyze this video$20.00/monthReads the picture and the audio..." on screen. */
.up-analyze-title { display: block; font-weight: 600; font-size: 13.5px; color: var(--text); }
.up-analyze-sub { display: block; font-size: 12.5px; color: var(--text-2); margin-top: 3px; line-height: 1.45; }
.up-analyze-price {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 10px;
  background: var(--accent-bg); color: var(--accent);
  font-size: 11.5px; font-weight: 700; vertical-align: 1px;
}
.up-analyze.is-on { border-color: var(--accent); }
/* A creator who already pays should not be shown a price tag. */
.up-analyze.is-subscribed .up-analyze-price { display: none; }

/* ------------------------------------------------------------- the confirmation
   THE THING THAT WAS MISSING. An upload that succeeds has to SAY SO, unmistakably, in the
   place the creator is already looking - which is the bottom of the dialog, next to the
   progress bar they were watching, not a notice at the top that is scrolled off screen.
   Three words of small green text on a row is not a confirmation. */
.up-done { margin-top: 20px; }
.up-done-head {
  display: flex; align-items: center; gap: 12px;
  font-size: 17px; font-weight: 600; line-height: 1.3;
  padding: 16px 18px; border-radius: 10px; margin-bottom: 12px;
}
.up-done-head.ok {
  background: #e6f4ea; color: #12652b; border: 1px solid #bfe3c9;
}
.up-done-head.warn {
  background: #fff4e5; color: #8a4b00; border: 1px solid #f5d9b0;
}
.up-done-head svg { flex-shrink: 0; }
[data-theme="dark"] .up-done-head.ok {
  background: #14301d; color: #86e0a3; border-color: #22562f;
}
[data-theme="dark"] .up-done-head.warn {
  background: #38260d; color: #f0c07a; border-color: #6b4a16;
}

.up-prog { height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; margin: 10px 0 6px; }
.up-prog > i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .2s ease; }
.up-state { font-size: 12.5px; color: var(--text-2); }

@media (max-width: 560px) {
  .up-item-meta { display: none; }
  .up-drop { padding: 24px 14px; }
}

/* Two 300px columns are unusable, so it stacks. The player is capped harder so the
   form still has room on a phone. */
@media (max-width: 900px) {
  .ed-cols { flex-direction: column; overflow-y: auto; }
  .ed-media, .ed-body { flex: 0 0 auto; max-width: none; height: auto; overflow: visible; }
  .ed-media video, .ed-media img { max-height: 30vh; }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 Roboto, "Segoe UI", -apple-system, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Keyboard users must always be able to see where they are. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- top bar */
.st-top {
  position: fixed; top: 0; left: 0; right: 0; height: var(--top-h); z-index: 30;
  display: flex; align-items: center; gap: 8px;
  padding: 0 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.st-burger {
  width: 40px; height: 40px; min-width: 40px;
  display: grid; place-items: center;
  background: none; border: none; border-radius: 50%; cursor: pointer;
  color: var(--text);
}
.st-burger:hover { background: var(--surface-2); }

/* text-decoration and color are NOT optional here. This is an <a>, and without them the
   browser default applied: the wordmark rendered with a blue underline running under
   "PitoReel" and "Studio". The child spans set their own colour, which is why the text
   looked right while the underline stayed blue and gave it away. */
.st-brand {
  display: flex; align-items: center; gap: 6px; margin-right: 8px;
  text-decoration: none;
  color: inherit;
}
.st-brand:hover, .st-brand:focus, .st-brand:visited { text-decoration: none; color: inherit; }
.st-brand-word {
  font-size: 19px; font-weight: 700; letter-spacing: -.4px; white-space: nowrap;
  display: inline-flex; align-items: center;
}
.st-brand-word .a { color: var(--text); }
.st-brand-word .b { color: var(--gold); }
/* The "o" is the PitoReel mark, the same as every other page on the platform. Rendering
   a plain letter "o" is not the logo. */
.st-brand-word svg { width: 19px; height: 19px; margin: 0 1px; color: var(--text); }
.st-brand-sub {
  font-size: 15px; color: var(--text-2); font-weight: 400;
  border-left: 1px solid var(--line); padding-left: 10px; margin-left: 4px;
}

/* Search sits centred like YouTube Studio's, and gives up width before the
   controls on its right do. */
.st-search { flex: 1; display: flex; justify-content: center; min-width: 0; }
.st-search form {
  width: 100%; max-width: 640px; position: relative; display: flex; align-items: center;
}
.st-search input {
  width: 100%; height: 40px;
  padding: 0 16px 0 44px;
  border: 1px solid var(--line); border-radius: 20px;
  background: var(--surface-2);
  font: inherit; color: var(--text); outline: none;
}
.st-search input:focus { background: var(--surface); border-color: #c6c6c6; }
.st-search svg { position: absolute; left: 14px; color: var(--text-2); pointer-events: none; }

.st-actions { display: flex; align-items: center; gap: 4px; }
.st-icon {
  width: 40px; height: 40px; min-width: 40px;
  display: grid; place-items: center;
  background: none; border: none; border-radius: 50%; cursor: pointer;
  color: var(--text-2); position: relative; text-decoration: none;
}
.st-icon:hover { background: var(--surface-2); color: var(--text); }
.st-badge {
  position: absolute; top: 6px; right: 5px; min-width: 15px; height: 15px;
  padding: 0 4px; border-radius: 8px; background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 700; display: none; place-items: center; line-height: 15px;
  text-align: center;
}
.st-create {
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 16px; margin-left: 4px;
  border: 1px solid var(--line); border-radius: 20px;
  background: var(--surface); color: var(--text);
  font: inherit; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.st-create:hover { background: var(--surface-2); }
.st-avatar {
  width: 32px; height: 32px; border-radius: 50%; margin-left: 8px;
  background: var(--surface-2); object-fit: cover; border: none; cursor: pointer;
  display: block;
}

/* ------------------------------------------------------------------- rail */
.st-rail {
  position: fixed; top: var(--top-h); left: 0; bottom: 0; width: var(--rail-w);
  z-index: 20; overflow-y: auto; overflow-x: hidden;
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding-bottom: 24px;
}
.st-chan { padding: 24px 12px 16px; text-align: center; }
.st-chan-pic {
  width: 112px; height: 112px; border-radius: 50%; margin: 0 auto 12px;
  background: var(--surface-2); object-fit: cover; display: block;
}
.st-chan-label { font-size: 14px; color: var(--text); }
.st-chan-name { font-size: 12px; color: var(--text-2); margin-top: 2px; word-break: break-word; }

.st-nav { padding: 0 0 8px; }
.st-nav a {
  display: flex; align-items: center; gap: 24px;
  min-height: 44px; padding: 0 24px;
  color: var(--text); font-size: 14px; text-decoration: none;
  border-left: 3px solid transparent;
}
.st-nav a:hover { background: var(--surface-2); text-decoration: none; }
.st-nav a.active {
  background: var(--accent-bg); border-left-color: var(--accent);
  color: var(--text); font-weight: 500;
}
.st-nav a.active .st-ico { color: var(--accent); }
.st-ico { width: 24px; min-width: 24px; display: grid; place-items: center; color: var(--text-2); }
.st-nav-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st-sep { height: 1px; background: var(--line); margin: 8px 0; }
.st-group {
  font-size: 12px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-3); padding: 12px 24px 6px;
}

/* Collapsed rail: icons only, labels hidden. */
body.st-collapsed .st-rail { width: var(--rail-w-sm); }
body.st-collapsed .st-rail .st-nav-label,
body.st-collapsed .st-rail .st-chan-label,
body.st-collapsed .st-rail .st-chan-name,
body.st-collapsed .st-rail .st-group { display: none; }
body.st-collapsed .st-chan-pic { width: 40px; height: 40px; }
body.st-collapsed .st-chan { padding: 16px 8px 8px; }
body.st-collapsed .st-nav a { padding: 0 24px; gap: 0; justify-content: flex-start; }
body.st-collapsed .st-main { margin-left: var(--rail-w-sm); }

/* ------------------------------------------------------------------- main */
.st-main {
  margin-left: var(--rail-w); padding-top: var(--top-h);
  min-height: 100vh;
}
.st-page { max-width: 1284px; padding: 24px 24px 80px; }
.st-h1 { font-size: 24px; font-weight: 400; margin: 0 0 24px; letter-spacing: -.2px; }
.st-h2 { font-size: 16px; font-weight: 500; margin: 0 0 12px; }

.st-head-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 24px;
}
.st-head-row .st-h1 { margin: 0; }

/* --------------------------------------------------------------- surfaces */
.st-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 20px;
}
.st-grid { display: grid; gap: 24px; }
.st-grid-3 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.st-grid-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.st-stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; }
.st-stat-k { font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); }
.st-stat-v { font-size: 28px; font-weight: 400; margin-top: 6px; letter-spacing: -.5px; }
.st-stat-n { font-size: 12px; color: var(--text-3); margin-top: 2px; }

/* ----------------------------------------------------------------- tabs */
.st-tabs {
  display: flex; gap: 24px; border-bottom: 1px solid var(--line);
  margin-bottom: 20px; overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.st-tab {
  background: none; border: none; cursor: pointer;
  padding: 12px 2px; min-height: 44px;
  font: inherit; font-weight: 500; color: var(--text-2);
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.st-tab:hover { color: var(--text); }
.st-tab.active { color: var(--text); border-bottom-color: var(--text); }

/* --------------------------------------------------------------- buttons */
.st-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 36px; padding: 0 16px;
  border: 1px solid var(--line); border-radius: 18px;
  background: var(--surface); color: var(--text);
  font: inherit; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.st-btn:hover { background: var(--surface-2); text-decoration: none; }
.st-btn-primary { background: var(--text); color: #fff; border-color: var(--text); }
.st-btn-primary:hover { background: #272727; }
.st-btn-accent { background: var(--accent); color: #fff; border-color: var(--accent); }
.st-btn-accent:hover { background: #0b57c2; }
.st-btn-danger { color: var(--danger); border-color: #f3c2c1; background: var(--surface); }
.st-btn-danger:hover { background: #fdeceb; }
.st-btn-sm { min-height: 32px; padding: 0 12px; font-size: 13px; }

/* ---------------------------------------------------------------- tables */
.st-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.st-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.st-table th {
  text-align: left; font-size: 12px; font-weight: 500; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .05em;
  padding: 12px 12px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.st-table td { padding: 14px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.st-table tr:hover td { background: #fafafa; }
.st-table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ empty state */
.st-empty { text-align: center; padding: 64px 24px; color: var(--text-2); }
.st-empty h3 { font-size: 16px; font-weight: 500; color: var(--text); margin: 0 0 6px; }
.st-empty p { margin: 0 auto 20px; max-width: 420px; }

/* An empty list, a failed request and a feature that does not exist yet are
   three different facts. Never render one as another. */
.st-note {
  border: 1px solid var(--line); background: var(--surface);
  border-radius: 10px; padding: 14px 16px; color: var(--text-2);
}
.st-note.warn { background: var(--gold-bg); border-color: #f0e0b0; color: #6b5200; }
.st-note.err { background: #fdeceb; border-color: #f3c2c1; color: #8c1d1b; }

.st-chip {
  display: inline-block; padding: 3px 9px; border-radius: 10px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  background: var(--surface-2); color: var(--text-2);
}
/* --ok on the pale green chip is 3.92:1 at 11px, just under AA. Darkened; the pale
   green background keeps the "published" signal. */
.st-chip.ok { background: #e6f4ea; color: #10683a; }
.st-chip.warn { background: var(--gold-bg); color: #6b5200; }
.st-chip.err { background: #fdeceb; color: var(--danger); }

.st-spin {
  width: 28px; height: 28px; margin: 40px auto; display: block;
  border: 3px solid var(--line); border-top-color: var(--accent);
  border-radius: 50%; animation: st-rot .8s linear infinite;
}
@keyframes st-rot { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------- dialogs */
.st-backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0,0,0,.5);
  display: none; align-items: center; justify-content: center; padding: 20px;
  overflow: hidden;                 /* the SHEET scrolls, not the backdrop */
}
.st-backdrop.open { display: flex; }
.st-sheet {
  background: var(--surface); border-radius: 12px;
  width: 100%; max-width: 960px; max-height: calc(100vh - 56px);
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 12px 48px rgba(0,0,0,.3);
}
.st-sheet-head {
  flex-shrink: 0; padding: 20px 24px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.st-sheet-head h2 { margin: 0; font-size: 20px; font-weight: 400; }
.st-sheet-body { flex: 1; overflow-y: auto; min-height: 0; padding: 24px; }
.st-sheet-foot {
  flex-shrink: 0; padding: 16px 24px; border-top: 1px solid var(--line);
  display: flex; justify-content: flex-end; gap: 12px;
}
/* The page behind a dialog must not scroll. */
body.st-locked { overflow: hidden; }

/* ----------------------------------------------------------------- forms */
.st-field { margin-bottom: 20px; }
.st-label { display: block; font-size: 12px; color: var(--text-2); margin-bottom: 6px; }
.st-input, .st-select, .st-textarea {
  width: 100%; padding: 10px 12px; min-height: 40px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); color: var(--text); font: inherit; outline: none;
}
.st-input:focus, .st-select:focus, .st-textarea:focus { border-color: var(--accent); }
.st-textarea { min-height: 120px; resize: vertical; }
.st-check { display: flex; align-items: flex-start; gap: 12px; min-height: 44px; cursor: pointer; }
.st-check input { width: 18px; height: 18px; margin-top: 3px; flex-shrink: 0; cursor: pointer; }

/* ------------------------------------------------------------- responsive */
@media (max-width: 1100px) {
  .st-rail { width: var(--rail-w-sm); }
  .st-rail .st-nav-label, .st-rail .st-chan-label,
  .st-rail .st-chan-name, .st-rail .st-group { display: none; }
  .st-chan-pic { width: 40px; height: 40px; }
  .st-chan { padding: 16px 8px 8px; }
  .st-main { margin-left: var(--rail-w-sm); }
  body.st-collapsed .st-rail { width: 0; border-right: none; }
  body.st-collapsed .st-main { margin-left: 0; }
}

@media (max-width: 800px) {
  /* The rail becomes a drawer. It starts hidden so the content gets the width. */
  .st-rail {
    width: var(--rail-w); transform: translateX(-100%);
    transition: transform .18s ease; box-shadow: 0 0 40px rgba(0,0,0,.2);
  }
  .st-rail .st-nav-label, .st-rail .st-chan-label,
  .st-rail .st-chan-name, .st-rail .st-group { display: block; }
  .st-chan-pic { width: 88px; height: 88px; }
  .st-main { margin-left: 0; }
  body.st-drawer .st-rail { transform: translateX(0); }
  body.st-drawer .st-scrim { display: block; }
  .st-scrim {
    display: none; position: fixed; inset: var(--top-h) 0 0 0;
    background: rgba(0,0,0,.4); z-index: 19;
  }
  /* The logo, search and avatar must all stay visible on a phone. */
  .st-brand-sub { display: none; }
  /* THE CREATE LABEL STAYS. Hiding it left a bare glyph that nobody can read - the same
     defect the owner photographed on the browse page. The room came from removing Analyze
     Video from the bar entirely: it was an unreadable symbol AND a duplicate of a sidebar
     item that already carries the words. */
  .st-create { padding: 0 10px; }
  .st-create span { font-size: 13px; }
  .st-page { padding: 16px 16px 64px; }
  .st-h1 { font-size: 20px; }

  /* TOUCH TARGETS. 44px minimum on every top-bar control - a phone has no hover
     and no pointer precision, so a 40px icon is a miss waiting to happen. The
     brand gets the same height so the wordmark is a comfortable tap back to the
     Dashboard rather than a 26px sliver. */
  .st-burger, .st-icon, .st-create {
    min-width: 44px; min-height: 44px;
  }
  /* Every button, not just the top bar. .st-btn is 36px on desktop, which is fine
     with a mouse and a miss waiting to happen with a thumb - and "End stream" is
     exactly the button you do not want someone stabbing at twice. */
  .st-btn { min-height: 44px; }
  .st-brand { min-height: 44px; }
  .st-avatar { width: 34px; height: 34px; }
}

/* THE TOP BAR ON A PHONE. Measured, not estimated.
   With the search field plus Help plus the theme toggle in the bar, the controls need
   444px. On the owner's 390px phone that put the avatar 62px PAST the right edge and
   clipped Create, and the search field - squeezed to 56px - had the Help icon drawn on top
   of it. That grey pill with a "?" in it is what he photographed.

   Widths of the parts that must always survive: 16 pad + 44 menu + 8 + 74 wordmark + 8
   + 44 bell + 4 + 92 Create + 8 + 34 avatar + 16 pad = 348px. That fits 360px.

   So the search input goes first, then Help and the theme toggle - and those two move into
   the drawer (st-only-phone) rather than vanishing. Create KEEPS ITS WORD at every width:
   a bare glyph is the defect this bar already had once. */
@media (max-width: 768px) {
  /* A 56px search box is not a search box, and the Content page has the real one. */
  .st-search { display: none; }
}
@media (max-width: 470px) {
  #stHelp, #stTheme { display: none; }
}
/* Only shown once their top-bar equivalents are hidden, so a control never has two routes.

   THE SELECTOR HAS TO BE AT LEAST AS SPECIFIC AS `.st-nav a`, OR IT DOES NOTHING.
   A bare `.st-only-phone { display: none }` is (0,1,0) and `.st-nav a { display: flex }`
   further up this file is (0,1,1), so the anchor won on specificity no matter what order
   the rules were in - and Help and Appearance sat in the drawer at DESKTOP width too,
   giving each of them two routes, which is the thing the owner has objected to three times.
   Scoping to `.st-nav a.st-only-phone` (0,2,1) is what makes the rule real. */
.st-nav a.st-only-phone,
.st-nav div.st-only-phone { display: none; }
@media (max-width: 470px) {
  .st-nav a.st-only-phone { display: flex; }
  .st-nav div.st-only-phone { display: block; }
}

@media (max-width: 430px) {
  .st-brand-word { font-size: 17px; }
  .st-search input { padding-left: 38px; }
  .st-search svg { left: 11px; }
}
