/* ── OctoDecks shared UI ──────────────────────────────────────────────────────
   One definition of the app's colours and common controls, loaded first by
   every page so a page's own <style> can still adjust layout. Pages keep their
   own theme variables (--accent, --red …); the tokens below read those, so they
   follow light / dark theme automatically.

     Tokens ........ colours, radii, backdrop, focus
     Focus ......... one keyboard focus ring everywhere
     Pop-ups ....... .oct-backdrop, .oct-panel, .oct-panel-head
     Inputs ........ .oct-input
     Buttons ....... .oct-add  .oct-del  .oct-close  .oct-sec  .oct-submit
     Icons ......... .oi .oi-<name>   (drawn shapes, never font glyphs)
     Switch ........ .oct-switch (.on)
     Tips .......... .oct-tip  (ⓘ with a hover / focus bubble)
     Hints ......... .oct-hint[data-hint]  (what a control does, below it on hover / focus)
     Chips ......... .oct-chip  (.oct-chip-accent / -danger / -success / -muted)
     Notice ........ .oct-notice  (page-wide warning bar along the bottom, e.g. server unreachable)
     Screen reader . .sr-only  (read aloud, not shown — live regions, hidden labels)

   Rule for + and ✕ (and any other icon): never paint them with a font glyph —
   glyphs sit off-centre. Draw them with an image / mask, as below. */

/* ── Tokens ───────────────────────────────────────────────────────────────
   Plain colour values only — no color-mix(): the slide exporter (html2canvas)
   can't read the colours it produces and the whole PDF/PPTX export fails.
   Defaults are the dark theme (deck pages' default); [data-theme="light"]
   swaps them. Interactive Sessions (light by default) sets its own in styles.css.
   Tint steps (-a06 … -a40) replace hand-typed rgba() tints of the brand colours. */
:root {
  --oct-accent: var(--accent, #6b9fd4);
  --oct-accent-hover: #4a86c5;
  --oct-accent-soft: rgba(107, 159, 212, .12);
  --oct-accent-a06: rgba(107, 159, 212, .06);
  --oct-accent-a10: rgba(107, 159, 212, .10);
  --oct-accent-a15: rgba(107, 159, 212, .15);
  --oct-accent-a20: rgba(107, 159, 212, .20);
  --oct-accent-a30: rgba(107, 159, 212, .30);
  --oct-accent-a40: rgba(107, 159, 212, .40);
  --oct-danger: var(--red, #ef4444);
  --oct-danger-hover: #dc2626;
  --oct-danger-soft: rgba(239, 68, 68, .11);
  --oct-danger-a06: rgba(239, 68, 68, .06);
  --oct-danger-a10: rgba(239, 68, 68, .10);
  --oct-danger-a15: rgba(239, 68, 68, .15);
  --oct-danger-a20: rgba(239, 68, 68, .20);
  --oct-danger-a30: rgba(239, 68, 68, .30);
  --oct-danger-a40: rgba(239, 68, 68, .40);
  --oct-success: #10b981;
  --oct-success-soft: rgba(16, 185, 129, .13);
  --oct-success-a06: rgba(16, 185, 129, .06);
  --oct-success-a10: rgba(16, 185, 129, .10);
  --oct-success-a15: rgba(16, 185, 129, .15);
  --oct-success-a20: rgba(16, 185, 129, .20);
  --oct-success-a30: rgba(16, 185, 129, .30);
  --oct-success-a40: rgba(16, 185, 129, .40);
  --oct-warn: #f59e0b;
  --oct-warn-soft: rgba(245, 158, 11, .14);
  --oct-warn-a10: rgba(245, 158, 11, .10);
  --oct-warn-a20: rgba(245, 158, 11, .20);
  --oct-warn-a40: rgba(245, 158, 11, .40);
  --oct-muted: var(--muted, #7a7268);
  --oct-muted-soft: rgba(127, 127, 127, .16);

  --oct-r-sm: 6px;      /* icon buttons */
  --oct-r: 8px;         /* text buttons, inputs */
  --oct-r-menu: 12px;   /* menus, pop-overs */
  --oct-r-panel: 16px;  /* pop-up panels */
  --oct-r-pill: 999px;  /* main actions, chips */

  --oct-backdrop: rgba(12, 12, 16, .55);        /* behind a pop-up / dialog */
  --oct-backdrop-strong: rgba(8, 8, 10, .82);   /* behind full-screen media (photos, video) */
  --oct-backdrop-blur: 4px;
  --oct-shadow-panel: 0 24px 60px rgba(0, 0, 0, .28), 0 2px 8px rgba(0, 0, 0, .12);
  --oct-shadow-menu: 0 12px 32px rgba(0, 0, 0, .22), 0 2px 6px rgba(0, 0, 0, .10);

  --oct-focus: var(--oct-accent);
}
[data-theme="light"] {
  --oct-accent-hover: #2f6696;
  --oct-accent-soft: rgba(61, 122, 176, .12);
  --oct-accent-a06: rgba(61, 122, 176, .06);
  --oct-accent-a10: rgba(61, 122, 176, .10);
  --oct-accent-a15: rgba(61, 122, 176, .15);
  --oct-accent-a20: rgba(61, 122, 176, .20);
  --oct-accent-a30: rgba(61, 122, 176, .30);
  --oct-accent-a40: rgba(61, 122, 176, .40);
  --oct-danger-hover: #b91c1c;
  --oct-danger-soft: rgba(220, 38, 38, .10);
  --oct-danger-a06: rgba(220, 38, 38, .06);
  --oct-danger-a10: rgba(220, 38, 38, .10);
  --oct-danger-a15: rgba(220, 38, 38, .15);
  --oct-danger-a20: rgba(220, 38, 38, .20);
  --oct-danger-a30: rgba(220, 38, 38, .30);
  --oct-danger-a40: rgba(220, 38, 38, .40);
}

/* Shapes drawn as images / masks (white for coloured circles, black = mask) */
:root {
  --oct-img-plus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M6 1.5v9M1.5 6h9' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  --oct-img-x: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3.2 3.2l5.6 5.6M8.8 3.2l-5.6 5.6' stroke='%23fff' stroke-width='1.9' stroke-linecap='round'/%3E%3C/svg%3E");
  --oct-mask-x: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3.2 3.2l5.6 5.6M8.8 3.2l-5.6 5.6' stroke='%23000' stroke-width='1.9' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ── Focus: one visible ring for keyboard users, everywhere ──────────────────
   !important because many older rules switch outlines off; mouse clicks don't
   trigger :focus-visible on buttons, so this only shows for keyboard use.
   Text fields keep their own focus border (.oct-input). */
:is(button, a[href], summary, [role="button"], [role="tab"], [role="switch"], [tabindex]:not([tabindex="-1"]):not(input):not(textarea):not(select)):focus-visible {
  outline: 2px solid var(--oct-focus) !important;
  outline-offset: 2px !important;
}

/* ── Pop-ups ──────────────────────────────────────────────────────────────── */
.oct-backdrop {
  position: fixed; inset: 0; z-index: 9000;
  background: var(--oct-backdrop);
  -webkit-backdrop-filter: blur(var(--oct-backdrop-blur)); backdrop-filter: blur(var(--oct-backdrop-blur));
}
.oct-panel {
  background: var(--card, var(--bg-card, #fff)); color: var(--text, var(--text-primary, #222));
  border: 1px solid var(--border, var(--border-color, rgba(0,0,0,.1)));
  border-radius: var(--oct-r-panel); box-shadow: var(--oct-shadow-panel);
}
.oct-panel-head { display: flex; align-items: center; gap: 10px; padding: 14px 14px 10px 20px; }
.oct-panel-head > :first-child { flex: 1; min-width: 0; font-weight: 700; }

/* ── Inputs ───────────────────────────────────────────────────────────────── */
.oct-input {
  width: 100%; box-sizing: border-box; padding: 8px 11px;
  border: 1.5px solid var(--border, var(--border-color, #d4d4d4)); border-radius: var(--oct-r);
  background: var(--bg, var(--bg-white, #fff)); color: var(--text, var(--text-primary, #222));
  font: inherit; font-size: .8rem; transition: border-color .12s, box-shadow .12s;
}
.oct-input:focus, .oct-input:focus-visible {
  outline: none; border-color: var(--oct-accent); box-shadow: 0 0 0 3px var(--oct-accent-soft);
}

/* Every text field (any page) shows focus the same way: accent border + soft ring */
:is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]), textarea, select):focus-visible {
  border-color: var(--oct-accent); box-shadow: 0 0 0 3px var(--oct-accent-soft); outline: none;
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */
/* Add: solid circle + white plus, label beside it */
.oct-add {
  display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px 4px 3px;
  border: none; border-radius: var(--oct-r-pill); background: none; color: var(--text, var(--text-primary, #222));
  font-family: inherit; font-size: .74rem; font-weight: 600; line-height: 1.2;
  text-align: left; cursor: pointer; transition: background .12s;
}
.oct-add::before {
  content: ''; flex: 0 0 20px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--oct-accent) var(--oct-img-plus) center / 11px no-repeat; transition: background-color .12s;
}
.oct-add:hover { background: var(--oct-accent-soft); }
.oct-add:hover::before { background-color: var(--oct-accent-hover); }
.oct-add:disabled { opacity: .4; cursor: default; }

/* Remove from a list: grey ✕ (a mask, so it takes the text colour), red on hover */
.oct-del {
  flex-shrink: 0; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: var(--oct-r-sm); background: none; color: var(--oct-muted);
  font-size: 0 !important; line-height: 0; cursor: pointer; transition: color .12s, background .12s;
}
.oct-del::before {
  content: ''; width: 11px; height: 11px; background: currentColor;
  -webkit-mask: var(--oct-mask-x) center / contain no-repeat; mask: var(--oct-mask-x) center / contain no-repeat;
}
.oct-del:hover { color: var(--oct-danger); background: var(--oct-danger-soft); }

/* Close a pop-up / panel: round 32px ✕ */
.oct-close {
  flex-shrink: 0; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; background: none; color: var(--oct-muted);
  font-size: 0 !important; line-height: 0; cursor: pointer; transition: background .12s, color .12s;
}
.oct-close::before {
  content: ''; width: 13px; height: 13px; background: currentColor;
  -webkit-mask: var(--oct-mask-x) center / contain no-repeat; mask: var(--oct-mask-x) center / contain no-repeat;
}
.oct-close:hover { background: rgba(127, 127, 127, .15); color: var(--text, var(--text-primary, #222)); }

/* Secondary action in a panel: thin solid outline */
.oct-sec {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: var(--oct-r);
  border: 1px solid var(--border, var(--border-color, #d4d4d4)); background: none; color: var(--oct-accent);
  font-family: inherit; font-size: .66rem; font-weight: 600; line-height: 1.2; cursor: pointer; transition: border-color .12s, background .12s;
}
.oct-sec:hover { border-color: var(--oct-accent); background: var(--oct-accent-soft); }
.oct-sec:disabled { opacity: .45; cursor: default; }

/* Main action (students' Submit etc.): blue pill */
.oct-submit {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 11px 26px;
  border: none; border-radius: var(--oct-r-pill); background: var(--oct-accent); color: #fff;
  font-family: inherit; font-weight: 700; cursor: pointer; transition: background .12s, opacity .12s;
}
.oct-submit:hover { background: var(--oct-accent-hover); }
.oct-submit:disabled { opacity: .4; cursor: default; }

/* ── Icons: .oi .oi-<name> — a 1em shape in the current text colour ────────── */
.oi {
  display: inline-block; width: 1.05em; height: 1.05em; flex-shrink: 0; vertical-align: -0.16em;
  background: currentColor; -webkit-mask: var(--oi) center / contain no-repeat; mask: var(--oi) center / contain no-repeat;
}
.oi-pull     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2v8M4.5 6.5 8 10l3.5-3.5M3 13.5h10'/%3E%3C/svg%3E"); }
.oi-upload   { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 11V3M4.5 6.5 8 3l3.5 3.5M3 13.5h10'/%3E%3C/svg%3E"); }
.oi-download { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3v8M4.5 7.5 8 11l3.5-3.5M3 13.5h10'/%3E%3C/svg%3E"); }
.oi-refresh  { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13 8a5 5 0 1 1-1.6-3.7M13 2.5v3h-3'/%3E%3C/svg%3E"); }
.oi-undo     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5.5 4 2.5 7l3 3M3 7h6.5a4 4 0 0 1 0 8H7'/%3E%3C/svg%3E"); }
.oi-redo     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.5 4l3 3-3 3M13 7H6.5a4 4 0 0 0 0 8H9'/%3E%3C/svg%3E"); }
.oi-back     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13 8H3M7 4 3 8l4 4'/%3E%3C/svg%3E"); }
.oi-speaker  { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.2h2.4L8.5 3v10L4.9 9.8H2.5z'/%3E%3Cpath d='M11 5.6a3.4 3.4 0 0 1 0 4.8M12.9 3.7a6 6 0 0 1 0 8.6'/%3E%3C/svg%3E"); }
.oi-stop     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect x='3.5' y='3.5' width='9' height='9' rx='1.5' fill='%23000'/%3E%3C/svg%3E"); }
.oi-up       { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 13V3M4 7l4-4 4 4'/%3E%3C/svg%3E"); }
.oi-down     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3v10M4 9l4 4 4-4'/%3E%3C/svg%3E"); }
.oi-copy     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'%3E%3Crect x='5.5' y='5.5' width='8' height='8' rx='1.5'/%3E%3Cpath d='M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2'/%3E%3C/svg%3E"); }
.oi-check    { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5 6.5 12 13 4.5'/%3E%3C/svg%3E"); }
.oi-cross    { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m4 4 8 8M12 4l-8 8'/%3E%3C/svg%3E"); }
.oi-freeze   { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M8 1.5v13M2.4 4.75l11.2 6.5M2.4 11.25l11.2-6.5M6 2.5 8 4l2-1.5M6 13.5 8 12l2 1.5'/%3E%3C/svg%3E"); }
.oi-idea     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5h4M6.5 14.5h3M8 1.5a4.5 4.5 0 0 0-2.6 8.2c.4.3.6.8.6 1.3v.5h4V11c0-.5.2-1 .6-1.3A4.5 4.5 0 0 0 8 1.5Z'/%3E%3C/svg%3E"); }
.oi-pin      { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'%3E%3Cpath d='M8 14.5s4.5-4.2 4.5-7.5a4.5 4.5 0 0 0-9 0c0 3.3 4.5 7.5 4.5 7.5Z'/%3E%3Ccircle cx='8' cy='7' r='1.6'/%3E%3C/svg%3E"); }
.oi-edit     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.5 2.5l3 3-8 8H2.5v-3l8-8Z'/%3E%3C/svg%3E"); }
.oi-play     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.5 2.8v10.4a.6.6 0 0 0 .9.5l8.2-5.2a.6.6 0 0 0 0-1L5.4 2.3a.6.6 0 0 0-.9.5Z'/%3E%3C/svg%3E"); }
.oi-expand   { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10'/%3E%3C/svg%3E"); }
.oi-external { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 2.5h4.5V7M13.5 2.5 7 9M11.5 9.5v3a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h3'/%3E%3C/svg%3E"); }
.oi-eye      { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.5 8S4 3.5 8 3.5 14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8Z'/%3E%3Ccircle cx='8' cy='8' r='2'/%3E%3C/svg%3E"); }
.oi-eye-off  { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 3.7A6.6 6.6 0 0 1 8 3.5C12 3.5 14.5 8 14.5 8a12 12 0 0 1-1.8 2.4M10.1 10.1A2 2 0 0 1 5.9 5.9M4.1 4.6C2.4 5.8 1.5 8 1.5 8S4 12.5 8 12.5c1.2 0 2.3-.4 3.2-1M2 2l12 12'/%3E%3C/svg%3E"); }
.oi-lock     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='7' width='10' height='7.5' rx='1.5'/%3E%3Cpath d='M5.5 7V5a2.5 2.5 0 0 1 5 0v2'/%3E%3C/svg%3E"); }
.oi-unlock   { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='7' width='10' height='7.5' rx='1.5'/%3E%3Cpath d='M5.5 7V5a2.5 2.5 0 0 1 4.9-.7'/%3E%3C/svg%3E"); }
.oi-more     { --oi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='3' cy='8' r='1.5'/%3E%3Ccircle cx='8' cy='8' r='1.5'/%3E%3Ccircle cx='13' cy='8' r='1.5'/%3E%3C/svg%3E"); }

/* ── Switch ───────────────────────────────────────────────────────────────── */
.oct-switch {
  /* reset so a <button class="oct-switch"> matches a <div> one — a button's own
     border and padding would push the knob off-centre */
  -webkit-appearance: none; appearance: none; box-sizing: border-box; display: inline-block;
  margin: 0; padding: 0; border: 0; vertical-align: middle;
  position: relative; flex-shrink: 0; width: 34px; height: 20px; border-radius: 999px;
  background: rgba(127, 127, 127, .35); cursor: pointer; transition: background .15s;
}
.oct-switch::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .25); transition: transform .15s;
}
.oct-switch.on { background: var(--oct-accent); }
.oct-switch.on::after { transform: translateX(14px); }

/* ── Tips: a small ⓘ that shows its text on hover or keyboard focus ─────────── */
.oct-tip {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 50%; vertical-align: -2px; margin-left: 4px;
  font-size: 10px; font-weight: 700; font-style: normal; line-height: 1; cursor: help;
  color: var(--oct-muted); border: 1.3px solid currentColor;
}
.oct-tip::after {
  content: attr(data-tip); position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%);
  width: max-content; max-width: 240px; padding: 7px 10px; border-radius: var(--oct-r);
  background: #1f2023; color: #fff; font-size: 12px; font-weight: 500; line-height: 1.4; text-align: left; white-space: normal;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .25); opacity: 0; pointer-events: none; transition: opacity .12s; z-index: 50;
}
.oct-tip:hover::after, .oct-tip:focus-visible::after { opacity: 1; }

/* ── Hints: explain what a toolbar control does, in a bubble below it ────────
   Shown on mouse hover (not on touch, where :hover sticks after a tap) and on
   keyboard focus; hidden while the control's own menu is open. */
.oct-hint { position: relative; }
.oct-hint::after {
  content: attr(data-hint); position: absolute; left: 50%; top: calc(100% + 8px); transform: translateX(-50%);
  width: max-content; max-width: 220px; padding: 7px 10px; border-radius: var(--oct-r);
  background: #1f2023; color: #fff; font: 500 12px/1.4 system-ui, sans-serif; letter-spacing: normal;
  text-transform: none; text-align: left; white-space: normal;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .25); opacity: 0; pointer-events: none; transition: opacity .12s .25s; z-index: 300;
}
@media (hover: hover) { .oct-hint:hover::after { opacity: 1; } }
.oct-hint:focus-visible::after { opacity: 1; }
.oct-hint[aria-expanded="true"]::after { opacity: 0 !important; }
.oct-hint-end::after { left: auto; right: 0; transform: none; } /* control at the right edge */
.oct-hint[data-hint-align="start"]::after { left: 0; transform: none; }   /* set by the page near the left edge */
.oct-hint[data-hint-align="end"]::after { left: auto; right: 0; transform: none; }

/* ── Chips ────────────────────────────────────────────────────────────────── */
.oct-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 3px 10px; border-radius: var(--oct-r-pill); font-size: .72rem; font-weight: 600; line-height: 1.4;
  background: var(--oct-muted-soft); color: var(--text, var(--text-primary, #222));
}
.oct-chip-accent  { background: var(--oct-accent-soft);  color: var(--oct-accent); }
.oct-chip-danger  { background: var(--oct-danger-soft);  color: var(--oct-danger); }
.oct-chip-success { background: var(--oct-success-soft); color: #059669; }
.oct-chip-muted   { background: transparent; border: 1px solid var(--border, var(--border-color, #d4d4d4)); color: var(--oct-muted); }

/* ── Notice ────────────────────────────────────────────────────────────────
   A page-wide warning that stays until dismissed (js/firebase-fallback.js). */
.oct-notice {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 2147483000;
  display: flex; align-items: center; gap: 12px; max-width: min(640px, calc(100vw - 32px));
  padding: 10px 12px 10px 16px; border-radius: var(--oct-r-menu);
  background: var(--card, var(--surface, #fff)); color: var(--text, #1f1d1a);
  border: 1px solid var(--oct-warn-a40); box-shadow: var(--oct-shadow-menu);
  font: 500 13px/1.45 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
}
.oct-notice::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--oct-warn); }
.oct-notice button {
  flex: none; margin-left: auto; min-height: 32px; padding: 0 12px; border-radius: var(--oct-r);
  border: 1px solid var(--oct-warn-a40); background: var(--oct-warn-a10); color: inherit; font: inherit; cursor: pointer;
}

/* ── Screen reader ─────────────────────────────────────────────────────────
   Read aloud but not drawn — for live announcements and labels that the
   visual layout already makes obvious. */
.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;
}
