/* antitribu.io dashboard — shared styles for index.html, /news/ article pages,
   trial-rotation, login/account/admin.
   Scoped to these pages only; combined.css (used by classes/, trials/, other/) is untouched.
   Dark palette only, no light-mode variant. Full-width, scrolling layout. */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;800&display=swap');
:root{
  --bg:#121013; --panel:#1a171b; --panel-2:#221e22; --border:#2e282c;
  /* Mint Ice & Berry (mockups/color-palette/gallery.html, "16") -- chosen
     2026-08-12 to replace the original rust/gold/teal trio, then adjusted
     several more times the same day: --accent and --teal swapped (accent
     became the old teal blue, teal became the old accent green), --teal
     replaced with the pink from palette mockup "12. Lavender Field"'s
     teal-equivalent role, then --accent/--gold matched EXACTLY to the S/A
     tier hexes (#d81f2c / #a64dff) -- and finally --teal (the site's other
     pink, missed in that pass) matched to the same A-tier purple as
     --gold, so there is no pink left anywhere in the palette, only the
     literal tier red and tier purple. --accent-dim is a newly-computed
     darker match for the new red; --gold/--teal have no dim variants.
     background/panel/border/text/tier colors are untouched. */
  --text:#ece7e4; --text-dim:#9c9391; --accent:#d81f2c; --accent-dim:#771118; --teal:#a64dff; --gold:#a64dff;
  --sans:-apple-system,"Segoe UI",Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",Consolas,"Roboto Mono",monospace;
  --brand-font:'Poppins',var(--sans);
  /* Nav mega-menu / footer column accent bars only -- six sequential vivid
     rainbow stops, red through purple, assigned by column identity so the
     same category is always the same color in both the top nav and the
     footer (nav.js/footer.js reference these by name; there's no per-
     column "5th/6th" indexing to keep in sync between the two). Previously
     these all just reused --accent/--teal/--gold, which meant most columns
     collapsed to two colors (and, after those tokens became tier red/
     purple, ALL columns read as one of two colors). Unrelated to the tier
     colors or the --accent/--teal/--gold remap above. */
  --nav-red:#ff3b30; --nav-orange:#ff9500; --nav-yellow:#ffcc00;
  --nav-green:#34c759; --nav-blue:#0a84ff; --nav-purple:#af52de;
}
*{box-sizing:border-box;}
html,body{margin:0;}
/* Safety net: nothing on this site should ever need to grow the page wider
   than the viewport (any horizontal scrolling belongs to a specific
   element, e.g. .article-grid, that owns its own overflow-x:auto) — this
   catches the class of bug where a runaway child (an overflowing nav
   panel, a too-wide table) drags the *whole page* wider instead of being
   clipped or scrolling internally. */
html{overflow-x:hidden;}
body{background:var(--bg);color:var(--text);font-family:var(--sans);font-size:15px;line-height:1.6;overflow-x:hidden;}
a{color:inherit;text-decoration:none;}

/* Safety net #2: an empty contenteditable [data-field] element must never
   become invisible or unclickable. Real incident (2026-08-12): a Healing
   Stats field was cleared and saved -- the now-empty element rendered with
   no usable click target, so the field was still there in the data and the
   DOM but there was nothing left to click to type new text back into it.
   This treatment used to exist only for the tier-list justification
   paragraphs (added after an earlier, narrower version of the same bug);
   it's sitewide now so no future editable field can get stuck the same way.
   min-height alone doesn't affect plain-inline elements (some [data-field]
   spans are, e.g. the class-guide stat tiles), hence the inline-block
   override on those; table cells/headings/divs are already block or
   table-cell and don't need it. iframe/img are excluded -- their
   data-field marks the element for a URL/upload-based edit control, not
   typed text, and every page already keeps them out of contenteditable
   (applyEditableState()'s own skip-list in each page's JS), so they're
   always structurally "empty" here regardless of whether real content is
   set. */
.editing [data-field]:empty:not(iframe):not(img){min-height:1.4em;outline:1px dashed var(--border);outline-offset:2px;border-radius:3px;}
.editing span[data-field]:empty:not(iframe):not(img){display:inline-block;min-width:70px;}
.editing [data-field]:empty:not(iframe):not(img)::before{content:"Click to edit…";color:var(--text-dim);font-style:italic;opacity:.6;}

/* top bar + mega-menu nav */
header.top{border-bottom:1px solid var(--border);position:relative;z-index:40;}
.topbar{display:flex;align-items:center;gap:24px;padding:16px 28px;width:100%;flex-wrap:wrap;}
.brand{font-weight:600;font-size:16px;flex:none;font-family:var(--brand-font);}

nav.primary{display:flex;align-items:stretch;gap:0;font-size:13.5px;margin-left:8px;}
nav.primary > a,nav.primary .mega-trigger,.nav-logout-btn,.nav-admin-link{display:flex;align-items:center;gap:5px;padding:8px 14px;color:var(--text-dim);background:none;border:none;font:inherit;text-decoration:none;cursor:pointer;}
nav.primary > a:hover,.mega:hover .mega-trigger,.mega:focus-within .mega-trigger{color:var(--text);}
/* Sibling of nav.primary inside .topbar (a flex row), not a nav item
   itself — margin-left:auto pins the GROUP to the far right, opposite the
   brand, regardless of how many nav items precede it. The auto margin lives
   on the group, not on nav-logout-btn/nav-admin-link individually, so the
   two sit flush together instead of each claiming its own share of space. */
.nav-auth-group{display:flex;align-items:center;gap:6px;margin-left:auto;}
.nav-logout-btn{color:var(--accent);font-weight:700;}
.nav-logout-btn:hover{color:var(--text);}
.nav-admin-link:hover{color:var(--text);}
.mega-trigger .chev{font-size:10px;transition:transform .15s;}
.mega:hover .mega-trigger .chev,.mega:focus-within .mega-trigger .chev{transform:rotate(180deg);}
.mega{position:relative;}
/* Anchored to .mega (the small trigger), so a panel wider than the space
   remaining to the viewport's right edge would overflow off-screen with
   nothing clipping it -- that overflow is what was dragging the entire
   page wider on narrow windows. Two independent guards: a hard max-width
   tied to the viewport (not just the trigger), and nav.js flips
   .align-right on (in practice, once the panel's real width is known) so
   it can hang from its right edge instead of its left when the left-anchor
   would run off-screen. */
/* width:max-content, not the default auto, is load-bearing here: an
   absolutely-positioned flex container with flex-wrap:wrap and an auto
   width has no unambiguous "available space" to shrink-to-fit against, and
   collapses to roughly one column wide with the rest wrapping below it
   even though the viewport has plenty of room. max-content forces it to
   size to its columns' natural (unwrapped) width first; max-width then
   only clips it back down -- and wrapping only engages -- once that
   natural width actually doesn't fit. */
.mega-panel{display:none;position:absolute;top:100%;left:0;width:max-content;max-width:calc(100vw - 32px);background:var(--panel);border:1px solid var(--border);border-top:2px solid var(--accent);padding:22px 26px;gap:28px;box-shadow:0 20px 44px rgba(0,0,0,.5);z-index:50;flex-wrap:wrap;overflow-y:auto;max-height:calc(100vh - 90px);}
.mega-panel.align-right{left:auto;right:0;}
.mega:hover .mega-panel,.mega:focus-within .mega-panel{display:flex;}
.mega-col{min-width:170px;}
.mega-col h3{display:flex;align-items:center;gap:9px;font-size:12.5px;text-transform:uppercase;letter-spacing:.05em;margin:0 0 10px;color:var(--text);}
.mega-col h3::before{content:"";width:3px;height:14px;background:var(--col,var(--accent));display:inline-block;border-radius:1px;}
.mega-col a{display:block;padding:4px 0;font-size:13.5px;color:var(--text-dim);white-space:nowrap;}
.mega-col a:hover{color:var(--accent);}

/* full-width layout */
.page{padding:28px;display:flex;gap:24px;align-items:flex-start;width:100%;}
.sidebar-col{width:280px;flex:none;display:flex;flex-direction:column;gap:16px;}
.main-col{flex:1;min-width:0;}

.tile{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:18px;}
.tile h2{font-size:12.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin:0 0 14px;}

/* vertical trial card */
.affix-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:8px;}
.affix-list-vertical{list-style:none;margin:0;padding:0;}
.affix-list-vertical li{border-top:1px solid var(--border);padding:8px 0;font-size:13px;}
.affix-list-vertical li:first-child{border-top:none;}

/* affix name -> description tooltip, shared by the sidebar's vertical list
   (.affix-list-vertical li), any other inline affix mention (.affix-chip,
   e.g. the full rotation table's comma-separated cell), and — reused for a
   different lookup, same mechanic — class name -> weapon-combo on the tier
   list (.combo-badge, .class-name-hover). All just need position:relative
   + cursor:help + a data-tip attribute to pick this up. */
.affix-list-vertical li,.affix-chip,.combo-badge,.class-name-hover{position:relative;cursor:help;}
.affix-chip,.class-name-hover{border-bottom:1px dotted var(--text-dim);}
.affix-list-vertical li:hover,.affix-list-vertical li:focus-visible,.affix-chip:hover,.affix-chip:focus-visible,.class-name-hover:hover,.class-name-hover:focus-visible{color:var(--teal);outline:none;}
.combo-badge:hover,.combo-badge:focus-visible{outline:none;}
.affix-list-vertical li::after,.affix-chip::after,.combo-badge::after,.class-name-hover::after{content:attr(data-tip);position:absolute;left:0;bottom:100%;margin-bottom:6px;width:230px;background:#0c0a0b;border:1px solid var(--border);color:var(--text);padding:9px;font-size:12px;line-height:1.45;border-radius:5px;opacity:0;pointer-events:none;transition:opacity .12s;z-index:30;box-shadow:0 10px 26px rgba(0,0,0,.5);}
.affix-list-vertical li:hover::after,.affix-list-vertical li:focus-visible::after,.affix-chip:hover::after,.affix-chip:focus-visible::after,.combo-badge:hover::after,.combo-badge:focus-visible::after,.class-name-hover:hover::after,.class-name-hover:focus-visible::after{opacity:1;}

/* trial rotation slider — one panel visible at a time, drag/wheel/arrow-key
   to switch, same interaction model as the games-selection wall. */
.trial-slider-wrap{display:flex;align-items:center;gap:8px;margin-bottom:16px;}
.trial-slider{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;flex:1;min-width:0;scrollbar-width:none;-webkit-overflow-scrolling:touch;touch-action:pan-x;}
.trial-slider::-webkit-scrollbar{display:none;}
.trial-slider.dragging{cursor:grabbing;user-select:none;}
.trial-slide{flex:0 0 100%;scroll-snap-align:start;text-align:center;padding:2px 4px;}
.trial-slide .slide-label{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);}
.trial-slide .slide-name{font-weight:800;font-size:17px;margin-top:3px;}
.trial-slide .slide-species{font-size:11.5px;color:var(--text-dim);margin-top:2px;}
.trial-slide.current .slide-name{color:var(--accent);}
.slide-btn{flex:none;width:26px;height:26px;border-radius:50%;border:1px solid var(--border);background:var(--panel-2);color:var(--text-dim);cursor:pointer;font-size:14px;line-height:1;padding:0;}
.slide-btn:hover{color:var(--text);border-color:var(--accent);}

.link-list{list-style:none;margin:0;padding:0;}
.link-list li a{display:block;padding:6px 0;font-size:13.8px;border-top:1px solid var(--border);}
.link-list li:first-child a{border-top:none;}
.link-list li a:hover{color:var(--accent);}

/* articles */
.section-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:16px;}
.section-head h2{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin:0;}
.article-grid{display:flex;gap:20px;overflow-x:auto;scroll-behavior:smooth;padding-bottom:8px;scrollbar-width:thin;-webkit-overflow-scrolling:touch;touch-action:pan-x;min-width:0;}
.article-grid.dragging{cursor:grabbing;user-select:none;}
.article-grid::-webkit-scrollbar{height:7px;}
.article-grid::-webkit-scrollbar-thumb{background:var(--border);border-radius:999px;}
.article-card{display:block;flex:0 0 320px;background:var(--panel);border:1px solid var(--border);border-radius:8px;overflow:hidden;}
/* var(--tc,...) so a card carrying its own --tc (class-guide/resource
   cards -- see the .rule-card-img comment below) hovers/links in that
   same color instead of the flat sitewide accent; every other card
   (Trial Guides, News) has no --tc declared and falls through to the
   fallback exactly as before. */
.article-card:hover{border-color:var(--tc,var(--accent));}
.article-img{aspect-ratio:16/9;background-size:cover;background-position:center;background-color:var(--panel-2);position:relative;overflow:hidden;}
/* Tier Rule, Left -- shared by class-guide cards (chosen from
   mockups/article-cards-class-guide/07-tier-rule-left.html) and the tier
   list card (chosen from mockups/article-cards-tier-list round 6, "Left
   Rule Lockup") so the two sit together as one family in the Articles
   strip. --tc defaults to gold; declared on the .article-card itself (not
   just this .article-img) so the card's hover border and "Read guide"
   link above pick it up too -- a class-guide card sets it to its live
   tier color via public/js/class-guide-cards.js once it knows one; the
   three Resources cards below set a fixed color each, one per card. */
.rule-card-img .rule-card-bar{position:absolute;left:0;top:0;bottom:0;width:7px;background:var(--tc,var(--gold));}
.rule-card-img .rule-card-text{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;padding-left:30px;}
.rule-card-img .rule-card-name{font-family:var(--brand-font);font-size:28px;font-weight:800;text-transform:uppercase;letter-spacing:-.01em;color:var(--text);line-height:1;}
.rule-card-img .rule-card-label{font-size:10px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;color:var(--tc,var(--gold));margin-top:8px;}
/* Corner Glyph (chosen from
   mockups/article-cards-resource-rework/gallery.html, "03. Corner Glyph")
   for reference pages (Heal Stats, Trial Rotation) -- supersedes the
   earlier Minimal Glyph + Glow treatment so these join the same
   .rule-card-img family as the class-guide/tier-list cards. --tc is teal
   here (the color already established sitewide for reference content),
   set inline since there's no tier data to drive it. A future reference
   page joins the set with its own glyph in the corner, same construction. */
.rule-card-img .rule-card-corner{position:absolute;top:12px;right:14px;color:var(--tc,var(--teal));opacity:.85;}
/* Trial Guide homepage cards only, for any guide not yet finished -- see
   FINISHED_GUIDES in trial-guide-widget.js. */
.rule-card-img .rule-card-unfinished{position:absolute;top:10px;left:19px;background:rgba(15,13,14,.72);border:1px solid var(--tc,var(--gold));color:var(--tc,var(--gold));font-size:9.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;padding:3px 7px;border-radius:4px;}
.article-body{padding:14px 16px 16px;}
.article-date{display:block;font-size:11.5px;color:var(--text-dim);margin-bottom:4px;}
.article-title{font-size:15.5px;font-weight:700;margin:0;}
.article-card:hover .article-title{color:var(--tc,var(--accent));}
.article-read{display:inline-block;margin-top:8px;font-size:12px;color:var(--tc,var(--teal));}

footer.site{border-top:1px solid var(--border);padding:28px 28px 20px;color:var(--text-dim);font-size:12.5px;}
.footer-grid{display:flex;flex-wrap:wrap;gap:32px;margin-bottom:20px;}
.footer-col{min-width:170px;}
.footer-col h3{display:flex;align-items:center;gap:9px;font-size:12px;text-transform:uppercase;letter-spacing:.05em;margin:0 0 10px;color:var(--text);}
.footer-col h3::before{content:"";width:3px;height:14px;background:var(--col,var(--accent));display:inline-block;border-radius:1px;}
.footer-col a{display:block;padding:3px 0;font-size:13px;color:var(--text-dim);white-space:nowrap;}
.footer-col a:hover{color:var(--accent);}
.footer-meta{border-top:1px solid var(--border);padding-top:14px;font-size:12px;}

/* pending-affixes notice (current trial has no mapped affix set yet) */
.affix-pending{font-size:12.5px;color:var(--text-dim);border:1px dashed var(--border);border-radius:6px;padding:10px 12px;}
.affix-pending a{color:var(--teal);}
@media (max-width:860px){
  /* The real cause of "the article strip doesn't scroll, the whole page
     is too wide": .page's align-items:flex-start governs the CROSS axis,
     which becomes width once flex-direction flips to column here. With
     flex-start (shrink-to-fit), .main-col was never stretched to .page's
     actual width -- it sized itself to its own widest content instead
     (.article-grid's un-clipped intrinsic row width, ~2000px), and
     everything downstream inherited that. align-items:stretch forces
     .main-col/.sidebar-col back to the container's real width, which is
     what lets .article-grid's own overflow-x:auto finally do its job
     instead of being made moot by an oversized parent. */
  .page{flex-direction:column;align-items:stretch;}
  .sidebar-col{width:100%;flex-direction:row;flex-wrap:wrap;}
  .sidebar-col .tile{flex:1;min-width:240px;}
}
/* Below this, treat it as a phone: the hover-driven mega-menu doesn't
   have room to sit beside its trigger and there's no hover to open it
   with anyway. Rather than reimplement it as a hamburger-toggled
   accordion (tried once, reverted -- it's more UI than this needs, and it
   very easily degrades into a header full-width dropdown breaking the
   above-860px hover layout by mistake), the primary nav just isn't shown
   here. footer.js's sitewide sitemap already lists every one of these
   links in one place and is always reachable by scrolling down, which
   is the more natural mobile pattern anyway. */
@media (max-width:640px){
  nav.primary{display:none;}
  .page{padding:16px;}
  .topbar{padding:14px 16px;}
}
/* Fixed px sizing reads small on large/high-res desktop monitors even though
   it's the same physical size as on a laptop. `zoom` (not transform:scale)
   reproduces an actual browser-zoom-style reflow at wide viewports — the
   user's own 133% manual zoom was the reference point for "looks right". */
@media (min-width:1700px){ html{ zoom:1.15; } }
@media (min-width:2200px){ html{ zoom:1.33; } }

/* article pages */
.article-shell{max-width:760px;margin:0 auto;padding:0 22px 60px;}
/* wide variant for content-dense reference pages (tables, etc.) where the
   default article width feels cramped — news/guide prose stays at the
   narrower default for readability, this is opt-in per page. */
.article-shell.wide{max-width:1100px;}
.article-hero{max-width:760px;height:280px;margin:24px auto 26px;background-size:cover;background-position:center;background-color:var(--panel-2);border-radius:8px;}
.back-link{display:inline-block;margin:22px 22px 0;font-size:13px;color:var(--text-dim);}
.back-link:hover{color:var(--accent);}
.article-shell h1{font-size:24px;margin:0 0 6px;}
.article-date-line{font-size:13px;color:var(--text-dim);margin:0 0 20px;}
.article-shell p{font-size:16px;line-height:1.7;}

/* generic in-page editing (trial guides, Healing Stats, and any future
   editable page) — a floating edit/save/cancel toolbar and a save toast.
   Pages using this should follow the trial-guide.js pattern: [data-field]
   elements go contenteditable in place, no separate admin form. */
.edit-toolbar{position:fixed;right:20px;bottom:20px;z-index:200;display:flex;gap:8px;}
.edit-toolbar[hidden]{display:none;}
.edit-toolbar button{padding:10px 18px;border-radius:999px;border:1px solid var(--border);font-size:13px;font-weight:700;cursor:pointer;font-family:inherit;}
.edit-toolbar .btn-edit{background:linear-gradient(100deg,var(--gold),var(--accent));color:#1a1210;border-color:transparent;}
.edit-toolbar .btn-save{background:var(--teal);color:#08211c;border-color:transparent;}
.edit-toolbar .btn-cancel{background:var(--panel-2);color:var(--text);}
.edit-toolbar button:hover{filter:brightness(1.08);}
.edit-toast{position:fixed;left:50%;bottom:78px;transform:translateX(-50%);background:var(--panel-2);border:1px solid var(--border);border-radius:999px;padding:9px 18px;font-size:13px;color:var(--text);box-shadow:0 10px 30px rgba(0,0,0,.5);z-index:200;opacity:0;pointer-events:none;transition:opacity .2s;}
.edit-toast.show{opacity:1;}
.editable-table{width:100%;border-collapse:collapse;font-size:14.5px;margin-bottom:10px;}
.editable-table th{text-align:left;padding:8px 10px 8px 0;color:var(--text-dim);font-size:11.5px;text-transform:uppercase;letter-spacing:.05em;border-bottom:1px solid var(--border);}
.editable-table td{padding:8px 10px 8px 0;border-bottom:1px solid var(--border);}
.editable-table tr:last-child td{border-bottom:none;}
.editing .editable-table td[contenteditable="true"],.editing .editable-table th[contenteditable="true"]{outline:1px dashed var(--border);outline-offset:2px;border-radius:3px;}
/* All Stats (other/all-stats.html) only -- its right column holds free-
   text values of unpredictable length, and this table's default
   content-driven auto layout let a single long value stretch that column
   wide enough to squeeze the left (Stat name) column down to almost
   nothing. Fixed layout + explicit widths on the first/last columns pins
   the Stat and Remove columns to a sane width and gives Value the rest of
   the row, with wrapping instead of overflow -- scoped to .stats-2col
   specifically so Healing Stats' own (differently-shaped) tables are
   untouched. */
.editable-table.stats-2col{table-layout:fixed;}
.editable-table.stats-2col th:first-child,.editable-table.stats-2col td:first-child{width:20%;}
.editable-table.stats-2col th:last-child,.editable-table.stats-2col td:last-child{width:76px;}
.editable-table.stats-2col td{overflow-wrap:anywhere;word-break:break-word;}
.editing h1[contenteditable="true"],.editing h2[contenteditable="true"]{outline:1px dashed var(--border);outline-offset:4px;border-radius:3px;}
.row-remove-btn{display:none;background:none;border:1px solid var(--border);color:var(--text-dim);border-radius:4px;padding:2px 8px;font-size:11px;cursor:pointer;font-family:inherit;}
.editing .row-remove-btn{display:inline-block;}
.row-remove-btn:hover{border-color:var(--accent);color:var(--accent);}
.table-add-btn{display:none;background:none;border:1px dashed var(--border);color:var(--text-dim);border-radius:6px;padding:6px 12px;font-size:12.5px;cursor:pointer;font-family:inherit;margin-bottom:24px;}
.editing .table-add-btn{display:inline-block;}
.table-add-btn:hover{border-color:var(--accent);color:var(--accent);}

/* healer tier list — built from mockups/tier-list/04-dot-pair-badges.html
   (the chosen "Outline Glow" row treatment), reworked per the owner: the
   dot-pair badge became a two-tone split pill, and each badge grows its
   own two-color glow (one shadow per half, tinted to that half's weapon)
   instead of relying only on the row's glow. Rows are a fixed min-height
   regardless of content so an empty tier is never visibly thinner. */
.tier-row{display:grid;grid-template-columns:70px 1fr;border-radius:6px;margin-bottom:16px;position:relative;background:var(--panel);min-height:88px;box-shadow:inset 0 0 0 1.5px var(--tier-color), 0 0 24px -6px var(--tier-color);}
.tier-label{display:flex;align-items:center;justify-content:center;font-size:26px;font-weight:900;color:var(--tier-color);}
.tier-body{min-height:88px;padding:16px 20px 16px 6px;display:flex;flex-wrap:wrap;gap:14px;align-items:center;}
/* Drop target feedback while dragging a class badge from another tier. */
.tier-body.drag-over{background:rgba(255,255,255,.04);outline:2px dashed var(--tier-color);outline-offset:-6px;border-radius:6px;}
/* Ghost outline (chosen from mockups/tier-list-badges-v2/06-ghost-outline-badges.html):
   transparent fill, a tier-colored inset border and tier-colored text --
   sits lighter on the row than the old solid-fill glow version. */
.combo-badge{display:inline-flex;align-items:center;justify-content:center;height:44px;padding:0 22px;border-radius:8px;
  background:transparent;
  box-shadow:inset 0 0 0 2px var(--tier-color);
  cursor:grab;}
.combo-badge.dragging{opacity:.4;cursor:grabbing;}
.combo-badge .combo-name{font-size:14px;font-weight:800;letter-spacing:.01em;color:var(--tier-color);white-space:nowrap;}
.combo-remove{display:none;position:absolute;top:-9px;right:-6px;font-size:9.5px;background:var(--bg);border:1px solid var(--border);color:var(--text-dim);border-radius:4px;padding:2px 6px;cursor:pointer;font-family:inherit;z-index:2;}
.editing .combo-remove{display:block;}
.tier-row-tools{position:absolute;top:8px;right:8px;display:none;gap:6px;}
.editing .tier-row-tools{display:flex;}
.tier-row-tools button{font-size:10.5px;background:var(--panel-2);border:1px solid var(--border);color:var(--text-dim);border-radius:4px;padding:3px 8px;cursor:pointer;font-family:inherit;}
.tier-row-tools button:hover{border-color:var(--accent);color:var(--accent);}
.tier-picker{display:none;gap:8px;align-items:center;margin-top:2px;}
.editing .tier-picker{display:flex;}
.tier-picker select{background:var(--panel-2);border:1px solid var(--border);color:var(--text);border-radius:6px;padding:6px 8px;font-size:12.5px;max-width:220px;}
.tier-picker button{padding:6px 12px;border-radius:6px;border:1px solid transparent;background:linear-gradient(100deg,var(--gold),var(--accent));color:#1a1210;font-weight:700;font-size:12px;cursor:pointer;font-family:inherit;}
.add-tier-row{display:none;border:1px dashed var(--border);border-radius:10px;padding:14px;text-align:center;color:var(--text-dim);font-size:13px;cursor:pointer;background:none;width:100%;font-family:inherit;}
.editing .add-tier-row{display:block;}
.tier-justification{margin-top:40px;border-top:1px solid var(--border);padding-top:24px;}
.tier-justification h2{font-size:15px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-dim);margin:0 0 16px;}
/* Grouped Under Tier (chosen from mockups/tier-list-justification-v2/09-grouped-under-tier.html):
   entries gather under one tier heading instead of repeating the tier on
   every line -- less repetition once a tier holds several classes, which
   is the normal case. A tier with zero classes renders no heading at all. */
.justification-tier-head{display:flex;align-items:center;gap:10px;margin:26px 0 12px;}
.justification-tier-head:first-child{margin-top:0;}
.justification-tier-label{font-size:13px;font-weight:900;color:var(--tc);letter-spacing:.1em;text-transform:uppercase;}
.justification-tier-rule{flex:1;height:1px;background:var(--tc);opacity:.35;}
.justification-item{margin-bottom:16px;padding-left:2px;}
.justification-item h3{margin:0 0 4px;font-size:13.5px;font-weight:800;}
.justification-item p{margin:4px 0 0;font-size:13px;color:var(--text-dim);line-height:1.6;}

/* class guide (Seeker, Oracle, ...) -- master-detail split from
   mockups/class-guide/11-master-detail-stat-tiles.html: a persistent left
   rail (section nav + build-target tiles below it) and a large detail
   pane that swaps per section with no page reload/re-scroll. */
.class-guide-layout{display:flex;max-width:1100px;margin:0 auto;min-height:80vh;}
.class-guide-rail{width:230px;flex:none;border-right:1px solid var(--border);padding:30px 0;}
.class-guide-rail .eyebrow{color:var(--teal);text-transform:uppercase;letter-spacing:.12em;font-size:11px;font-weight:700;padding:0 24px;}
.class-guide-rail h1{font-size:22px;margin:6px 0 22px;padding:0 24px;}
.class-guide-rail .nav-item{display:block;width:100%;text-align:left;background:none;border:none;color:var(--text-dim);padding:12px 24px;font-size:14px;cursor:pointer;font-family:inherit;border-left:3px solid transparent;}
.class-guide-rail .nav-item.active{color:var(--text);border-left-color:var(--gold);background:var(--panel);}
.class-guide-rail .nav-item:hover{color:var(--text);}
/* Short, single-line build-target tiles (owner: shorten these from the
   original two-line stacked mockup version) -- value and label side by
   side in one row, not stacked. */
.rail-tiles{margin-top:26px;padding:18px 24px 4px;border-top:1px solid var(--border);}
.rail-tiles .lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin-bottom:10px;}
.rail-tiles .tile{display:flex;align-items:baseline;gap:8px;background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:7px 10px;margin-bottom:6px;position:relative;}
.rail-tiles .tile-val{font-size:13.5px;font-weight:800;color:var(--gold);flex:none;white-space:nowrap;}
.rail-tiles .tile-label{font-size:11px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tile-remove-btn{display:none;position:absolute;top:-8px;right:-6px;font-size:9px;background:var(--bg);border:1px solid var(--border);color:var(--text-dim);border-radius:4px;padding:1px 5px;cursor:pointer;font-family:inherit;}
.editing .tile-remove-btn{display:block;}
.tile-add-btn{display:none;width:100%;background:none;border:1px dashed var(--border);color:var(--text-dim);border-radius:6px;padding:6px;font-size:11.5px;cursor:pointer;font-family:inherit;margin-top:2px;}
.editing .tile-add-btn{display:block;}

.class-guide-detail{flex:1;min-width:0;padding:32px 40px 100px;}
.detail{display:none;}
.detail.active{display:block;}
.detail h2{font-size:13px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-dim);margin:0 0 18px;}
.section-body{font-size:15.5px;line-height:1.7;white-space:pre-line;}
.section-images{display:flex;flex-wrap:wrap;gap:16px;margin-bottom:18px;}
.section-image{position:relative;flex:1;min-width:220px;max-width:100%;}
.section-image img{max-width:100%;border-radius:8px;border:1px solid var(--border);display:block;}
.img-caption{text-align:center;font-size:12.5px;color:var(--text-dim);margin:6px 0 0;}
.image-edit-controls{display:none;gap:6px;justify-content:center;margin-top:6px;}
.editing .image-edit-controls{display:flex;}
.image-edit-controls button{font-size:10.5px;background:var(--panel-2);border:1px solid var(--border);color:var(--text-dim);border-radius:4px;padding:3px 8px;cursor:pointer;font-family:inherit;}
.image-edit-controls button:hover{border-color:var(--accent);color:var(--accent);}
.image-add-btn{display:none;background:none;border:1px dashed var(--border);color:var(--text-dim);border-radius:6px;padding:8px 14px;font-size:12.5px;cursor:pointer;font-family:inherit;margin-bottom:18px;}
.editing .image-add-btn{display:inline-block;}
@media (max-width:760px){.class-guide-layout{flex-direction:column;}.class-guide-rail{width:100%;border-right:none;border-bottom:1px solid var(--border);}.rail-tiles{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;}.rail-tiles .tile{margin-bottom:0;}.class-guide-detail{padding:24px 20px 80px;}}

/* auth pages (login / account) */
.auth-shell{max-width:420px;margin:60px auto;padding:0 22px;}
.auth-card{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:26px 24px;margin-bottom:20px;}
.auth-card h1{font-size:19px;margin:0 0 6px;}
.auth-note{font-size:13.5px;color:var(--text-dim);line-height:1.5;margin:0 0 18px;}
.auth-card label{display:block;font-size:12.5px;color:var(--text-dim);margin-bottom:14px;}
.auth-card input{display:block;width:100%;margin-top:6px;padding:9px 10px;background:var(--panel-2);border:1px solid var(--border);border-radius:5px;color:var(--text);font-size:14px;font-family:inherit;}
.auth-card input:focus{outline:none;border-color:var(--accent);}
.auth-card button{width:100%;padding:10px;background:var(--accent);border:none;border-radius:5px;color:#fff;font-size:14px;font-weight:700;cursor:pointer;}
.auth-card button:hover{background:var(--accent-dim);}
.auth-error{color:#e28577;font-size:13px;margin:14px 0 0;}
.auth-hint{display:block;font-size:11.5px;color:var(--text-dim);opacity:.75;margin-top:5px;line-height:1.45;}
.auth-card button:disabled{opacity:.55;cursor:default;}
.auth-card a{color:var(--accent);}
.auth-success{color:var(--teal);font-size:13px;margin:14px 0 0;}
.auth-card textarea{display:block;width:100%;margin-top:6px;padding:9px 10px;background:var(--panel-2);border:1px solid var(--border);border-radius:5px;color:var(--text);font-size:14px;font-family:inherit;resize:vertical;}
.auth-card input:focus,.auth-card textarea:focus{outline:none;border-color:var(--accent);}

/* admin */
.admin-shell{max-width:880px;margin:40px auto;padding:0 22px 60px;}
.admin-shell h1{font-size:19px;margin:0 0 4px;}
.admin-shell .auth-card{margin-bottom:24px;}
.btn-sm{padding:6px 12px;background:var(--panel-2);border:1px solid var(--border);border-radius:5px;color:var(--text);font-size:12.5px;cursor:pointer;font-family:inherit;}
.btn-sm:hover{border-color:var(--accent);color:var(--accent);}
/* .auth-card styles its buttons as full-width primary actions, which is right
   for "Log In" / "Save Affixes" but wrong for the small inline controls in the
   card lists (Confirm/Delete on a queue row, Remove on a variant). Those are
   .btn-sm, but `.auth-card button` outranks a bare class, so the override has
   to be at least as specific. */
.auth-card button.btn-sm{width:auto;padding:6px 12px;font-size:12.5px;font-weight:400;
  background:var(--panel-2);border:1px solid var(--border);color:var(--text);}
.auth-card button.btn-sm:hover{background:var(--panel-2);border-color:var(--accent);color:var(--accent);}
/* Destructive actions shouldn't be one indistinguishable click away from the
   safe one sitting next to them. */
.btn-sm.danger,.auth-card button.btn-sm.danger{color:#e28577;border-color:rgba(226,133,119,.45);}
.btn-sm.danger:hover,.auth-card button.btn-sm.danger:hover{background:rgba(226,133,119,.12);border-color:#e28577;color:#e28577;}
.affix-row{display:flex;gap:10px;align-items:flex-start;margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid var(--border);}
.affix-row:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0;}
.affix-row .affix-fields{flex:1;min-width:0;}
/* .auth-card button{width:100%} (above) otherwise stretches this button to
   fill the flex row, squeezing the fields down to a sliver. */
.affix-row .affix-remove{width:auto;flex:none;align-self:flex-start;}
.icon-upload{display:flex;align-items:center;gap:10px;}
.icon-preview{width:44px;height:44px;border-radius:6px;background:var(--panel-2);background-size:cover;background-position:center;flex:none;border:1px solid var(--border);}
.article-list-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 0;border-top:1px solid var(--border);}
.article-list-row:first-child{border-top:none;}
.article-list-row .title{font-weight:600;font-size:14px;}
.article-list-row .date{color:var(--text-dim);font-size:12px;}

/* in-place article editing on the dashboard */
.section-head-actions{display:flex;align-items:center;gap:10px;}
.article-card{position:relative;}
.article-edit-btn{position:absolute;top:8px;right:8px;z-index:5;padding:5px 10px;background:rgba(18,16,19,.85);border:1px solid var(--border);border-radius:5px;color:var(--text);font-size:11.5px;cursor:pointer;font-family:inherit;backdrop-filter:blur(2px);}
.article-edit-btn:hover{border-color:var(--accent);color:var(--accent);}
dialog.editor-dialog{background:transparent;border:none;padding:0;max-width:560px;width:92vw;margin:auto;}
dialog.editor-dialog::backdrop{background:rgba(6,5,6,.72);}
dialog.editor-dialog .auth-card{margin-bottom:0;max-height:86vh;overflow-y:auto;}
