:root {
  --bg: #0b1120;
  --bg2: #0e1626;
  --card: #151d30;
  --card2: #1b2540;
  --ink: #e7eef8;
  --muted: #93a4bd;
  --line: #26324c;
  --brand: #3b82f6;
  --brand-2: #60a5fa;
  --brand-ink: #ffffff;
  --glow: rgba(59,130,246,.55);
  --bgglow: #16213c;   /* the soft radial highlight behind the page (re-tinted by Site colour) */
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; min-height: 100%; }
body {
  background: radial-gradient(1100px 600px at 80% -10%, var(--bgglow) 0%, var(--bg) 55%) fixed, var(--bg);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased; line-height: 1.4;
}
.material-symbols-outlined {
  font-family: "Material Symbols Outlined";
  font-weight: normal; font-style: normal; line-height: 1; letter-spacing: normal;
  text-transform: none; display: inline-block; white-space: nowrap; word-wrap: normal; direction: ltr;
}

.wrap { max-width: 1520px; margin: 0 auto; padding: 30px 22px 72px; position: relative; z-index: 1; }
/* Subtle data-network background animation — fixed behind everything, never blocks clicks. */
.bg-anim { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.topbar { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; margin-bottom: 26px; }
.topbar-left { display: flex; flex-direction: column; gap: 12px; flex: 0 0 auto; }
.topbar-actions { display: flex; gap: 8px; align-items: center; flex: 0 0 auto; }
.title { display: flex; align-items: center; gap: 12px; }
.search { position: relative; }
.search input { height: 40px; padding: 0 12px 0 38px; width: 480px; max-width: 100%; border: 1px solid var(--line); border-radius: 10px; background: var(--bg2); color: var(--ink); font: inherit; font-size: 14px; }
/* Search row. In the view-mode top zone it sits atop the left column and fills its width. */
.searchrow { margin: 0 0 22px; }
.searchrow .search { display: block; width: 100%; max-width: 100%; }
.searchrow .search input { width: 100%; }
.topzone-groups .searchrow { margin: 0 0 14px; }
.search input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 16px var(--glow); }
.search .material-symbols-outlined { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 20px; pointer-events: none; }
@media (max-width: 620px) { .search input { width: 150px; } }
.title h1 { font-size: 24px; font-weight: 700; margin: 0; letter-spacing: -.01em; }
.title .dot { width: 32px; height: 32px; border-radius: 10px; background: linear-gradient(135deg,#3b82f6,#60a5fa); display: grid; place-items: center; color: #fff; box-shadow: 0 0 22px var(--glow); }
.title .ver { align-self: center; margin-left: 2px; background: var(--card2); color: var(--brand-2); border: 1px solid var(--line); font: inherit; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; cursor: pointer; line-height: 1.4; }
.title .ver:hover { border-color: var(--brand); box-shadow: 0 0 12px var(--glow); }

/* Standalone square shortcuts beside the title (uploaded image, no text) */
/* Own full-width row directly under the top bar. */
.shortcuts { display: flex; flex-wrap: wrap; align-content: flex-start; gap: 10px; margin: 0 0 22px; }
.shortcut {
  position: relative; width: 54px; height: 54px; flex: 0 0 auto; border-radius: 13px;
  border: 1px solid var(--line); background: var(--card); color: var(--brand-2);
  display: grid; place-items: center; overflow: hidden; cursor: pointer; padding: 0;
  text-decoration: none; transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.shortcut:hover { transform: translateY(-3px); border-color: #3a4a6e; box-shadow: 0 10px 30px rgba(3,8,20,.6), 0 0 0 1px rgba(59,130,246,.25); }
.shortcut img { width: 100%; height: 100%; object-fit: contain; padding: 8px; }
.shortcut .ph { color: var(--muted); font-size: 24px; }
.shortcut.add { border-style: dashed; color: var(--muted); }
.shortcut.add .material-symbols-outlined { font-size: 24px; }
.shortcut .sc-remove {
  position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; border-radius: 50%;
  background: #dc2626; color: #fff; font-size: 11px; line-height: 18px; text-align: center;
  box-shadow: 0 1px 4px rgba(3,8,20,.6); opacity: 0; transition: opacity .12s ease;
}
.shortcut:hover .sc-remove { opacity: 1; }
.shortcut.preview { cursor: default; }
.shortcut.drag-over { border-color: #3b82f6; box-shadow: 0 0 0 2px rgba(59,130,246,.55); }
/* Equalizer (id86): far right of the shortcuts row, 3 icons wide × icon tall, only while music plays. */
.eq { flex: 0 0 auto; margin-left: auto; width: 182px; height: 54px; border-radius: 13px; border: 1px solid var(--line); background: var(--card); display: flex; align-items: flex-end; justify-content: center; gap: 5px; padding: 9px 12px; overflow: hidden; }
.eq i { display: block; width: 6px; height: 30%; border-radius: 3px 3px 0 0; background: linear-gradient(180deg, var(--brand, #3b82f6), var(--brand-2, #22d3ee)); animation-name: eqbounce; animation-timing-function: ease-in-out; animation-iteration-count: infinite; animation-direction: alternate; }
@keyframes eqbounce { from { height: 16%; opacity: .55; } to { height: 92%; opacity: 1; } }
@media (max-width: 760px) { .eq { width: 150px; } }
@media (prefers-reduced-motion: reduce) { .eq i { animation: none; height: 55%; } }
.shortcut.preview:hover { transform: none; box-shadow: none; border-color: var(--line); }

.btn {
  display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 16px;
  border-radius: 10px; border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font: inherit; font-weight: 400; font-size: 14px; cursor: pointer; transition: all .14s ease;
}
.btn:hover { border-color: #3a4a6e; background: var(--card2); }
.btn:disabled { opacity: .5; cursor: default; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
.btn-primary:hover { background: #2f6fe0; box-shadow: 0 0 18px var(--glow); }
.btn-sm { height: 32px; padding: 0 10px; font-size: 13px; border-radius: 8px; }
/* Small page-music player nested with the top-bar action buttons. */
.audioplayer { display: inline-flex; align-items: center; gap: 4px; }
.audioplayer .vol { width: 68px; accent-color: var(--brand); cursor: pointer; }
.btn-danger { color: #f87171; }

/* Groups & separators */
.group { margin-bottom: 30px; }
.group-head { display: flex; align-items: center; gap: 12px; margin: 0 2px 14px; }
.group-head h2, .group-edit { font-size: 12.5px; font-weight: 400; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin: 0; }
.group-edit { background: transparent; border: 1px dashed var(--line); border-radius: 7px; padding: 5px 8px; color: var(--ink); width: 220px; }
.group-edit:focus { outline: none; border-color: var(--brand); }
.group-head .rule { flex: 1; height: 1px; background: linear-gradient(90deg, var(--line), transparent); }
/* 6 links per row on desktop, scaling down for smaller screens. grid-auto-flow:
   dense lets singles backfill the gaps left by 2-column pair cells. */
.grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; grid-auto-flow: row dense; }
@media (max-width: 1280px) { .grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 1080px) { .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 820px)  { .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Top zone: first two groups trimmed to 3-per-row beside a reserved widget-space frame. */
.topzone { display: flex; gap: 18px; align-items: stretch; margin-bottom: 26px; }
.topzone-groups { flex: 1 1 620px; min-width: 0; max-width: 660px; }
.topzone-groups .group { margin-bottom: 18px; }
/* The last (only) primary group has no trailing margin, so the stretched
   widget-space bottom lines up exactly with the last icon row instead of
   overshooting by the 18px gap. */
.topzone-groups .group:last-child { margin-bottom: 0; }
.grid.grid-trim { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* No min-height: the topzone stretches both columns equally, so the widget-space bottom
   lines up exactly with the last row of the primary icon group (id119), view + edit. */
.widget-space { flex: 1 1 auto; min-width: 220px; border: 1px dashed var(--line); border-radius: 16px; display: grid; place-items: center; color: var(--muted); font-size: 12px; letter-spacing: .08em; text-transform: uppercase; background: rgba(255,255,255,.02); }
/* When the widget space holds widgets: top-align, scroll, normal text, and NO outer
   frame (the cards have their own borders — neater). The dashed frame + the Widgets
   title/config only show in edit mode. */
.widget-space.has-widgets { display: block; place-items: initial; padding: 0; position: relative; overflow: hidden; text-transform: none; letter-spacing: normal; color: var(--ink); border: none; background: none; }
/* The widget content fills the frame absolutely and scrolls INSIDE it, so the
   widget space height is driven only by the primary icon column — it always
   extends down to the icons' bottom line (even with no events) and never past it. */
.widget-space.has-widgets > div { position: absolute; inset: 0; overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none; }
.widget-space.has-widgets > div::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* Hide scrollbars but keep scrolling, used inside widgets (e.g. the calendar agenda). */
.noscroll { scrollbar-width: none; -ms-overflow-style: none; }
.noscroll::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ── Dashboard Central (Data Studio launcher modal) ───────────────────────── */
.modal.dashcentral { width: min(1280px, 95vw); max-width: none; max-height: 88vh; display: flex; flex-direction: column; padding: 18px 20px; }
.dashcentral-hd { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.dashcentral-search { display: flex; align-items: center; gap: 8px; margin: 12px 0; padding: 0 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); }
.dashcentral-search input { flex: 1; border: none; background: none; color: var(--ink); font: inherit; padding: 9px 0; outline: none; min-width: 0; }
.dashcentral-search .material-symbols-outlined { color: var(--muted); font-size: 18px; }
.dashcentral-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.dashgroup { margin-bottom: 14px; }
.dashgroup h4 { margin: 0 0 8px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.dashgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.dashtile { position: relative; min-width: 0; text-align: center; }
.dashtile-img { display: grid; place-items: center; width: 100%; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden; border: 1px solid var(--line); cursor: pointer; text-decoration: none; }
.dashtile-img img { width: 100%; height: 100%; object-fit: cover; }
.dashtile-glyph { font-size: 30px; line-height: 1; color: #fff; }
.dashtile-cam { position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border-radius: 7px; border: none; background: rgba(3,8,20,.55); color: #fff; cursor: pointer; display: grid; place-items: center; opacity: 0; transition: opacity .12s; }
.dashtile:hover .dashtile-cam { opacity: 1; }
@media (hover: none) { .dashtile-cam { opacity: .85; } }
.dashtile-title { margin-top: 6px; font-size: 11.5px; font-weight: 600; line-height: 1.25; color: var(--ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.dashtile-sub { font-size: 10.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 640px) { .dashgrid { grid-template-columns: repeat(auto-fill, minmax(101px, 1fr)); } }
.dashtile-edit { position: absolute; top: 6px; left: 6px; display: flex; gap: 4px; opacity: 0; transition: opacity .12s; }
.dashtile:hover .dashtile-edit { opacity: 1; }
.dashtile-edit button { width: 24px; height: 24px; border-radius: 7px; border: none; background: rgba(3,8,20,.55); color: #fff; cursor: pointer; display: grid; place-items: center; }
@media (hover: none) { .dashtile-edit { opacity: .85; } }
.editing .widget-space.has-widgets { border: 1px dashed var(--line); background: rgba(255,255,255,.02); }
/* Widgets flow in columns when there's width: the calendar takes the left,
   leaving room for another widget to the right; stacks to 1 column when narrow. */
/* The grid fills the whole pinned widget space (down to the primary icons' bottom
   line) and its columns stretch, so a lone widget — or the columns together —
   always occupy the full height rather than leaving a gap below. */
/* grid-auto-rows minmax(0,1fr) makes the (single, on desktop) row fill the pinned
   widget-space height, so each card is HEIGHT-BOUNDED — the calendar agenda then
   overflows and scrolls internally with the wheel (rather than the card growing to
   fit every event). On mobile the area stacks, so rows go back to content height. */
.widget-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); grid-auto-rows: minmax(0, 1fr); gap: 0 12px; align-items: stretch; flex: 1 1 auto; min-height: 0; }
.widget-grid .wcal { order: -1; }
@media (max-width: 760px) { .widget-grid { grid-auto-rows: auto; } }
/* Right-hand widget column: weather, Notes, News stacked; cards grow to fill the
   column height so the column also reaches the bottom line. */
.wside { display: flex; flex-direction: column; min-width: 0; }
.wside > * { flex: 1 1 auto; }
.wside > *:last-child { margin-bottom: 0; }
/* Edit-mode row actions: single button with a hover dropdown (id118). */
.rowmenu { position: relative; display: inline-flex; }
.rowmenu-pop { position: absolute; right: 0; top: 100%; margin-top: 4px; z-index: 30; display: none; flex-direction: column; gap: 4px; padding: 6px; background: var(--card, #0f172a); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 10px 30px rgba(3,8,20,.6); }
.rowmenu:hover .rowmenu-pop, .rowmenu:focus-within .rowmenu-pop { display: flex; }
.rowmenu-pop .btn { justify-content: flex-start; white-space: nowrap; gap: 6px; }
/* While a card's edit menu is open, lift the whole card above later sibling cards
   so the dropdown isn't painted behind them (each card is its own stacking context). */
.editing .link:hover, .editing .link:focus-within { z-index: 50; }
@media (max-width: 760px) {
  .topzone { flex-direction: column; gap: 12px; }
  .topzone-groups { max-width: none; flex-basis: auto; }
  .widget-space { min-height: 0; }
  /* On a phone, let the widget area flow with the page instead of being pinned to
     the icon-column height and scrolling internally — so every widget shows its
     full content and gets real vertical room. */
  .widget-space.has-widgets { position: static; overflow: visible; }
  .widget-space.has-widgets > div { position: static; overflow: visible; }
  /* One widget per row (no two on a line), each on its own with a vertical gap. */
  .widget-grid { grid-template-columns: 1fr; grid-auto-rows: auto; gap: 14px; }
  .wside { gap: 14px; }
  .wside > * { flex: 0 0 auto; }
  /* Give each widget genuine vertical space (calendar taller for its agenda). */
  .widget-grid .wcard { min-height: 120px; }
  .widget-grid .wcal { min-height: 260px; }
}
/* What's-new modal: roomy fixed-size panel on desktop (much wider than a normal modal),
   internal scroll + pagination; on small screens it just fits the viewport. */
/* Use .modal.changelog-modal (two classes) so this beats the later `.modal { max-width:460px }`
   rule regardless of source order — otherwise the modal stayed clamped to 460px. */
/* Auto-height so it sizes to the (few) entries on the page. Capped at 90vh (90dvh
   on mobile, accounting for browser chrome) so the header + Close stay on-screen;
   the entry list scrolls internally rather than pushing buttons off the viewport. */
.modal.changelog-modal { position: relative; width: min(1200px, 92vw); max-width: none; height: auto; max-height: 90vh; display: flex; flex-direction: column; }
.modal.changelog-modal .changelog-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* Always-visible close (×) in the top-right — the primary way to dismiss on mobile. */
.modal-x { position: absolute; top: 10px; right: 10px; width: 36px; height: 36px; border-radius: 9px; border: 1px solid var(--line); background: var(--card); color: var(--muted); cursor: pointer; display: grid; place-items: center; line-height: 0; z-index: 1; }
.modal-x:hover { color: var(--ink); border-color: var(--muted); }
@media (max-width: 600px) { .modal.changelog-modal { width: 94vw; max-height: 90dvh; padding: 20px 16px; } }
@media (max-width: 560px) { .grid.grid-trim { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Edit mode uses the same 6-col responsive grid; cards wrap their action buttons
   onto a second line when a column gets narrow. */
.editing .grid { grid-auto-flow: row; }
/* Keep edit cards the SAME fixed height as view cards: no wrapping, compact actions. */
.editing .link { flex-wrap: nowrap; }
.editing .row-actions { margin-left: auto; }
.editing .row-actions .btn-sm { height: 28px; padding: 0 6px; }

/* A joined production + staging pair: two cards side by side with a link glyph
   between, occupying two columns so they always stay on the same row (incl. mobile). */
.pair { grid-column: span 2; display: flex; align-items: center; gap: 6px; min-width: 0; }
.pair .link { flex: 1 1 0; min-width: 0; }
.joiner { flex: 0 0 auto; display: grid; place-items: center; color: var(--muted); }
.joiner .material-symbols-outlined { font-size: 17px; opacity: .8; }
/* In edit mode, a linked pair is wrapped in a green-bordered "Linked" box so you
   can see at a glance which two icons are joined. */
/* Same fixed height as a normal card — outline (not border/padding) so it adds no height. */
.pair-edit { align-items: stretch; height: 60px; gap: 6px; border-radius: 12px; background: rgba(52,211,153,.06); position: relative; outline: 1px dashed #34d399; outline-offset: -1px; }
.pair-edit .link { border-color: transparent; }
/* Middle grip — drag it to move both halves of the pair together. */
.pair-grip { flex: 0 0 auto; align-self: center; display: grid; place-items: center; width: 20px; cursor: grab; color: var(--muted); }
.pair-grip:hover { color: var(--brand-2); }
.pair-grip:active { cursor: grabbing; }
.pair-grip .material-symbols-outlined { font-size: 18px; }
.pair-edit::before { content: attr(data-linked); position: absolute; top: -8px; left: 12px; background: var(--bg2); color: #34d399; font-size: 9px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; padding: 1px 7px; border-radius: 6px; z-index: 3; }

/* A linked pair shown (view mode) as one rounded button: the single icon on the
   far left, then two equal run-targets each showing the label + its environment.
   Hover left = green (run production), hover right = red (run staging). */
.pair-card { grid-column: span 2; gap: 8px; }
.pair-card .half { flex: 1 1 0; min-width: 0; align-self: stretch; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; border-radius: 9px; text-decoration: none; color: var(--ink); transition: background .12s ease, box-shadow .12s ease; }
.pair-card .half-label { font-size: 12px; line-height: 1.2; max-width: 100%; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pair-card .half-tag { font-size: 9px; font-weight: 700; letter-spacing: .05em; color: var(--muted); opacity: .75; transition: color .12s ease, opacity .12s ease; }
.pair-card .half.left:hover { background: rgba(22,163,74,.16); box-shadow: inset 0 0 0 1.5px #16a34a; }
.pair-card .half.right:hover { background: rgba(220,38,38,.16); box-shadow: inset 0 0 0 1.5px #dc2626; }
.pair-card .half.left:hover .half-tag { color: #4ade80; opacity: 1; }
.pair-card .half.right:hover .half-tag { color: #f87171; opacity: 1; }

.link {
  position: relative;
  display: flex; align-items: center; gap: 11px; padding: 10px 12px; height: 60px; background: var(--card);
  border: 1px solid var(--line); border-radius: 12px; text-decoration: none; color: var(--ink);
  transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.link:hover { transform: translateY(-3px); border-color: #3a4a6e; box-shadow: 0 10px 30px rgba(3,8,20,.6), 0 0 0 1px var(--glow); }
/* Hover glow by type: production = green, staging = red, everything else = blue (default above). */
.link.glow-production:hover { border-color: #16a34a; box-shadow: 0 10px 30px rgba(3,8,20,.6), 0 0 0 1px rgba(22,163,74,.55), 0 0 24px rgba(22,163,74,.5); }
.link.glow-staging:hover { border-color: #dc2626; box-shadow: 0 10px 30px rgba(3,8,20,.6), 0 0 0 1px rgba(220,38,38,.55), 0 0 24px rgba(220,38,38,.5); }
.link.glow-none:hover { border-color: #3b82f6; box-shadow: 0 10px 30px rgba(3,8,20,.6), 0 0 0 1px rgba(59,130,246,.55), 0 0 24px rgba(59,130,246,.5); }
.link .ic {
  width: 36px; height: 36px; flex: 0 0 36px; border-radius: 10px; display: grid; place-items: center;
  background: linear-gradient(135deg, rgba(59,130,246,.18), rgba(96,165,250,.10)); color: var(--brand-2);
  font-size: 19px; transition: box-shadow .15s ease, transform .15s ease;
}
.link .ic .material-symbols-outlined { font-size: 21px; }
/* Staging / production marking, top-right corner of the card */
.badge {
  position: absolute; top: 7px; right: 8px; font-size: 9px; font-weight: 800; letter-spacing: .05em;
  line-height: 1; padding: 2px 5px; border-radius: 5px; color: #fff;
  box-shadow: 0 1px 4px rgba(3,8,20,.5); pointer-events: none;
}
.badge.stg { background: #dc2626; }
.badge.prd { background: #16a34a; }
/* "Protected" marker — a filled shield in the top-right corner of a primary link card.
   Colour escalates with the security level: red -> orange -> blue -> green. */
.shield-badge { position: absolute; top: 5px; right: 6px; line-height: 1; pointer-events: none; color: #dc2626; filter: drop-shadow(0 1px 3px rgba(3,8,20,.6)); }
.shield-badge .material-symbols-outlined { font-size: 16px; font-variation-settings: 'FILL' 1; }
.shield-badge.s-red, .shield-badge-inline.s-red { color: #dc2626; }
.shield-badge.s-orange, .shield-badge-inline.s-orange { color: #f59e0b; }
.shield-badge.s-blue, .shield-badge-inline.s-blue { color: #3b82f6; }
.shield-badge.s-green, .shield-badge-inline.s-green { color: #16a34a; }
.shield-badge.s-purple, .shield-badge-inline.s-purple { color: #9333ea; }
/* Editor: shield level picker (preview swatch + small styled dropdown). */
/* While the inline shield is held down (for the 1–5 keyboard shortcut). */
.shield-badge-inline.holding { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 6px; cursor: grabbing; }
.shield-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.shield-badge-inline { line-height: 1; display: inline-flex; color: #dc2626; }
.shield-badge-inline .material-symbols-outlined { font-size: 22px; font-variation-settings: 'FILL' 1; }
.shield-select { width: auto; min-width: 170px; flex: 0 0 auto; }

/* "Special" star — lower-right corner of the icon, same size/colours as the shield */
.star-badge { position: absolute; bottom: 5px; right: 6px; line-height: 1; pointer-events: none; color: #dc2626; filter: drop-shadow(0 1px 3px rgba(3,8,20,.6)); }
.star-badge .material-symbols-outlined { font-size: 16px; font-variation-settings: 'FILL' 1; }
.star-badge.s-red, .star-badge-inline.s-red { color: #dc2626; }
.star-badge.s-orange, .star-badge-inline.s-orange { color: #f59e0b; }
.star-badge.s-blue, .star-badge-inline.s-blue { color: #3b82f6; }
.star-badge.s-green, .star-badge-inline.s-green { color: #16a34a; }
.star-badge.s-purple, .star-badge-inline.s-purple { color: #9333ea; }
.star-badge-inline { line-height: 1; display: inline-flex; color: #dc2626; }
.star-badge-inline .material-symbols-outlined { font-size: 22px; font-variation-settings: 'FILL' 1; }
.link:hover .ic { box-shadow: 0 0 20px var(--glow); transform: scale(1.06); color: #93c5fd; }
/* Spin the symbol a full turn on hover. */
.link .ic > span { display: inline-block; transition: transform .55s cubic-bezier(.34, 1.4, .5, 1); }
.link:hover .ic > span { transform: rotate(360deg); }
/* Title + optional subtitle stacked beside the icon; one line each so every card
   stays the same fixed height. */
.link .lblwrap { display: flex; flex-direction: column; justify-content: center; min-width: 0; gap: 1px; flex: 1 1 auto; }
.link .lbl { font-weight: 400; font-size: 12.5px; min-width: 0; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.link .sub { font-size: 10.5px; color: var(--muted); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Edit mode — keep icon + label clearly readable */
.editing .link { cursor: grab; }
.editing .link .lbl { white-space: normal; line-height: 1.25; }
/* Reorder (move) drop target: blue dashed highlight + a "MOVE" pill — the
   counterpart to the green "LINKED" indicator used for joining two icons. */
.link.drag-over { outline: 2px dashed var(--brand); outline-offset: 2px; background: rgba(59,130,246,.12); }
.link.drag-over::after {
  content: "Move";
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  background: var(--brand); color: #fff; font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 10px; border-radius: 999px; white-space: nowrap; z-index: 6; box-shadow: 0 2px 6px rgba(3,8,20,.6);
}
/* Drag-to-link: dropping on a card's centre shows a green "linked" indicator. */
.link.link-target { outline: 2px solid #34d399; outline-offset: 2px; box-shadow: 0 0 0 3px rgba(52,211,153,.30), 0 0 22px rgba(52,211,153,.5); }
.link.link-target::after {
  content: "Linked";
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  background: #059669; color: #fff; font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 10px; border-radius: 999px; white-space: nowrap; z-index: 6; box-shadow: 0 2px 6px rgba(3,8,20,.6);
}
.link .pair-flag { display: inline-grid; place-items: center; color: var(--brand-2); flex: 0 0 auto; }
.link .pair-flag .material-symbols-outlined { font-size: 16px; }
.link .row-actions { margin-left: auto; display: flex; gap: 4px; flex: 0 0 auto; }

/* Group position picker (edit mode) */
.pos-label { display: inline-flex; align-items: center; gap: 5px; text-transform: none; letter-spacing: 0; font-weight: 400; }
.pos-select { height: 32px; border: 1px solid var(--line); border-radius: 8px; background: var(--card); color: var(--ink); font: inherit; font-size: 13px; padding: 0 6px; cursor: pointer; }
.pos-select:focus { outline: none; border-color: var(--brand); }

/* Login gate */
.gate { position: fixed; inset: 0; display: grid; place-items: center; padding: 22px;
  background: radial-gradient(900px 500px at 50% -10%, #16213c, var(--bg) 60%); }
.gate-card { width: 100%; max-width: 360px; text-align: center; background: var(--card); border: 1px solid var(--line);
  border-radius: 18px; padding: 32px 28px; box-shadow: 0 24px 70px rgba(3,8,20,.7); }
.gate-card h3 { margin: 0 0 4px; font-size: 20px; }

/* Modal */
.backdrop { position: fixed; inset: 0; background: rgba(3,8,20,.66); display: grid; place-items: center; z-index: 100; padding: 20px; }
.modal { width: 100%; max-width: 460px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 24px; box-shadow: 0 24px 60px rgba(3,8,20,.7); }
.modal.big { max-width: 760px; max-height: 86vh; display: flex; flex-direction: column; }
.modal h3 { margin: 0 0 6px; font-size: 18px; }
.modal p.sub, .gate-card p.sub { margin: 0 0 18px; color: var(--muted); font-size: 14px; }
.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.field label { font-size: 12px; font-weight: 400; color: var(--muted); }
.input { height: 40px; padding: 0 12px; border: 1px solid var(--line); border-radius: 9px; font: inherit; font-size: 14px; background: var(--bg2); color: var(--ink); }
.input:focus { outline: none; border-color: var(--brand); }
textarea.input { height: auto; padding: 10px 12px; }
.pin-input { letter-spacing: 12px; text-align: center; font-size: 24px; font-weight: 700; height: 56px; width: 100%; }
.err { color: #f87171; font-size: 13px; margin: 8px 0 0; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }

/* Icon picker */
.icongrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 6px; overflow: auto; padding: 4px; }
.iconbtn { aspect-ratio: 1; border: 1px solid var(--line); border-radius: 9px; background: var(--bg2); cursor: pointer; display: grid; place-items: center; color: var(--ink); transition: all .12s ease; }
.iconbtn:hover { background: var(--card2); border-color: var(--brand); box-shadow: 0 0 14px var(--glow); }
.iconbtn.sel { background: var(--brand); color: #fff; border-color: var(--brand); }
.iconbtn .material-symbols-outlined { font-size: 24px; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
/* Keep body text un-bold (only the TG Links header stays bold) */
.wrap p strong { font-weight: 400; }
code { color: var(--brand-2); }

/* ── Online Console (/console) — mobile-first secure dashboard ─────────────── */
/* Narrow & centred on phones; uses more horizontal space on a PC window. */
.cwrap { max-width: 980px; margin: 0 auto; padding: 16px 14px 60px; }
/* Desktop (id139): two columns — interaction left, status right; snaps to one column on narrow screens. */
.cbody { display: flex; flex-direction: column; }
.ccol { min-width: 0; }
@media (min-width: 1024px) {
  .cwrap { max-width: 1320px; }
  /* Left column (Recently sent / Now / Waiting) gets more room; the right column
     (Platforms / Recently done) is ~20% narrower. 3fr/2fr = 60% / 40%. */
  .cbody { display: grid; grid-template-columns: 3fr 2fr; gap: 0 18px; align-items: start; }
}
.chdr { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.ctitle { display: flex; align-items: center; gap: 8px; font-size: 18px; font-weight: 700; color: var(--ink); }
.ctitle .material-symbols-outlined { color: var(--brand-2); }
.ctitle .cver { font-size: 11px; font-weight: 700; color: var(--brand-2); background: var(--bg2); border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; align-self: center; }
.cmeta { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.cpill { font-size: 11px; font-weight: 700; color: #fff; padding: 1px 8px; border-radius: 999px; background: var(--brand); }
.cpill.bad { background: #b91c1c; }
.ccard { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; margin-bottom: 12px; }
.ccard h2 { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 0 0 8px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.cnow { margin: 0 0 6px; font-size: 14px; color: var(--ink); line-height: 1.4; }
.cmuted { color: var(--muted); font-size: 13px; }
.clist { list-style: none; margin: 0; padding: 0; }
.clist li { display: flex; gap: 8px; align-items: flex-start; padding: 6px 0; border-top: 1px solid var(--line); font-size: 13.5px; line-height: 1.4; color: var(--ink); }
.clist li:first-child { border-top: 0; }
.cic { flex: 0 0 auto; min-width: 14px; text-align: center; font-weight: 700; }
.s-done { color: var(--muted); } .s-done .cic { color: #34d399; }
.s-doing .cic { color: #e0b341; } .s-doing { color: #fff; }
.s-todo .cic { color: var(--muted); }
.s-wait .cic { color: #f59e0b; }
.cplat { align-items: center; flex-wrap: wrap; }
.cplat-name { font-weight: 600; }
.cplat-detail { flex-basis: 100%; color: var(--muted); font-size: 11.5px; padding-left: 22px; }
.cplat-links { flex-basis: 100%; padding-left: 22px; display: flex; gap: 14px; margin-top: 2px; }
.cplat-links a { font-size: 11.5px; color: var(--brand-2, #22d3ee); text-decoration: none; }
.cplat-links a:hover { text-decoration: underline; }
.cbadge { margin-left: auto; font-size: 10px; font-weight: 800; letter-spacing: .04em; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.cbadge.ok { background: #14532d; color: #bbf7d0; }
.cbadge.bad { background: #b91c1c; color: #fff; }
.cbadge.warn { background: #92400e; color: #fde68a; }
.crelay { font-family: ui-monospace, Consolas, monospace; font-size: 12px; white-space: pre-wrap; word-break: break-word; }
.ctag { flex: 0 0 auto; }
.ctag.sent { color: #34d399; } .ctag.cancelled { color: var(--muted); } .ctag.failed { color: #f87171; }
.cgate { min-height: 100vh; display: grid; place-items: center; padding: 22px; }
.cgate-card { width: 100%; max-width: 340px; background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 26px 22px; box-shadow: 0 24px 70px rgba(3,8,20,.7); }
.cinput { width: 100%; height: 46px; padding: 0 14px; margin-bottom: 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg2); color: var(--ink); font-size: 16px; }
.cinput:focus { outline: none; border-color: var(--brand); }
.cbtn { height: 38px; padding: 0 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); color: var(--ink); font: inherit; font-size: 14px; cursor: pointer; }
.cbtn.primary { width: 100%; height: 46px; background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; margin-top: 4px; }
.cbtn:disabled { opacity: .5; }
.cerr { color: #f87171; font-size: 13px; margin: 4px 0 8px; }
.ccmd { width: 100%; resize: vertical; min-height: 44px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg2); color: var(--ink); font: inherit; font-size: 15px; }
.ccmd:focus { outline: none; border-color: var(--brand); }
.ctok { font-family: ui-monospace, Consolas, monospace; font-size: 12.5px; word-break: break-all; background: var(--bg2); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; color: var(--brand-2); }
.cquick { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cvoice { display: flex; gap: 8px; margin-top: 8px; }
.cproj { font: inherit; font-size: 12px; cursor: pointer; color: var(--brand-2); background: var(--bg2); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; }
.cbtn.rec { background: #7f1d1d; border-color: #ef4444; color: #fff; }
.cbtn-icon { width: 38px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.cchip { font: inherit; font-size: 12px; cursor: pointer; color: var(--brand-2); background: var(--bg2); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; }
.cchip:active, .cchip:hover { border-color: var(--brand); background: var(--card2); }
.clist li.tappable { cursor: pointer; }
.clist li.tappable:hover { color: #fff; }
/* Collapsible sent/relayed message rows with View + Copy */
.chist { padding: 7px 0; border-top: 1px solid var(--line); }
.chist:first-child { border-top: 0; }
.chist-head { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.chist-spacer { flex: 1; }
.cmini { font: inherit; font-size: 11px; cursor: pointer; color: var(--brand-2); background: transparent; border: 1px solid var(--line); border-radius: 6px; padding: 2px 9px; }
.cmini:hover { border-color: var(--brand); background: var(--card2); }
.chist-text { font-family: ui-monospace, Consolas, monospace; font-size: 12px; white-space: pre-wrap; word-break: break-word; color: #dfe5ee; line-height: 1.4; }
.chist-text.clamp { display: -webkit-box; -webkit-line-clamp: 5; line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden; }

/* Mobile: let the top bar wrap so the title, search, shortcuts and actions stack
   cleanly instead of squashing into one cramped row. */
@media (max-width: 760px) {
  .wrap { padding: 18px 14px 56px; }
  .topbar { flex-wrap: wrap; gap: 12px; }
  .topbar-left { flex: 1 1 100%; }
  .search input { width: 100%; }
  /* Full-width wrapping action row so the buttons (incl. log out) never run off-screen. */
  .topbar-actions { order: 2; flex: 1 1 100%; flex-wrap: wrap; justify-content: flex-start; gap: 6px; }
  .audioplayer { flex-wrap: wrap; }
  .shortcuts { order: 3; flex-basis: 100%; }
}
@media (max-width: 420px) { .audioplayer .vol { width: 56px; } }

/* ══════════════════════════════════════════════════════════════════════
   basic_links customisations (Claude, updated 2026-07-08)
   1) Hide the widgets (calendar/notes/…) for now — reversible: delete this block.
   2) Groups in 3 COLUMNS (2 on medium screens), 2 links per row inside each
      group, clear gaps between groups (Tristan's mock-up, 2026-07-08).
   ══════════════════════════════════════════════════════════════════════ */

/* 1 — hide the widget panel */
.widget-space { display: none !important; }
.topzone-groups { max-width: none !important; flex-basis: auto !important; }

/* 2 — the groups live inside an UNNAMED div under .wrap (view mode:
   div > [.topzone > .topzone-groups > (.searchrow + first group)] + group×N),
   so the grid goes on that div via :has(). .topzone/.topzone-groups are
   flattened with display:contents so the first group (Favourites) sits in the
   same grid as the rest; the search row spans the full width. */
@media (min-width: 820px) {
  .wrap > div:has(> .topzone) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 36px 26px;              /* row gap keeps the groups clearly separated */
    align-items: start;
  }
  .topzone { display: contents !important; }
  .topzone-groups { display: contents !important; }
  .searchrow { grid-column: 1 / -1; margin: 0 !important; }
  .wrap > div:has(> .topzone) > *:not(.group):not(.topzone) { grid-column: 1 / -1; }
  .group { min-width: 0; margin-bottom: 0 !important; }
  /* exactly TWO links per row inside every group */
  .group .grid,
  .group .grid.grid-trim { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (min-width: 1200px) {
  .wrap > div:has(> .topzone) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* below 820px the app keeps its original stacked mobile layout */
