/* ============================================================
   GOBSTAGRAM — DESIGN REDUX v3
   Loaded after gobstagram.css and every older patch stylesheet
   (see includes/header.php), so it wins cascade ties against them.

   It is NOT the last <link> on the page -- components/, the vendor
   bundles, film-lab.css and tntsearch.css come after it. That is
   fine, and deliberate: those files only *read* --g-* tokens and
   share no selectors with this one, so nothing here is overridden.
   The invariant that actually matters is that this file is the last
   one to DEFINE a token, and ThemeTokenResolutionTest enforces it.

   What this file does:
   1. Defines the Theme Contract v2 tokens (--g-*) at :root using
      Palette v3 (the owner's 64-colour palette, every pairing
      measured for WCAG contrast — see project/research/palette-v3.md
      in the design handoff bundle).
   2. Defines the literal Win98 tri-tone bevel technique
      (--g-bevel98-*), built from those tokens.
   3. "Retires the old presets" (owner's redux directive): the whole
      site now reads the same tokens the opt-in profile-theme-v2 path
      used to gate behind a flag, instead of the hardcoded v1 hex.
   4. Recolours + rebevels the sitewide chrome (shell, header, nav,
      boxes/bands, every button family, inputs, tables, swiper
      controls) with the new palette and the 98.css bevel.
   5. Widens the fixed shell 800px -> 900px.

   Component-level surfaces (post card, composer, profile, pagination)
   have their own dedicated stylesheets loaded after this one; this
   file is the shared foundation they all build on.
   ============================================================ */

/* ============================================================
   1. THEME CONTRACT — canonical tokens, Palette v3 defaults.
   Same 91-key contract the profile Theme Studio already edits
   (see includes/composer_theme.php) — now seeded here as the
   sitewide default instead of only inside body.profile-theme-v2.
   ============================================================ */
:root{
/* ---- Palette v3 ramps ---- */
--g-navy-950:#101114;--g-navy-900:#1d3c66;--g-navy-800:#1d2247;--g-navy-700:#28628f;--g-navy-600:#258cb8;--g-navy-500:#33408f;--g-navy-450:#496ccc;--g-navy-400:#5897f5;--g-navy-300:#7fbef5;--g-navy-200:#42ceeb;--g-navy-100:#d7e0d9;
--g-orange-950:#33211b;--g-orange-900:#52321d;--g-orange-850:#8f4a39;--g-orange-800:#8f4a39;--g-orange-750:#855d30;--g-orange-700:#cc7041;--g-orange-650:#8f4a39;--g-orange-600:#eb9b54;--g-orange-500:#eb9b54;--g-orange-450:#f59f7f;--g-orange-400:#f5db93;--g-orange-300:#f5be6c;--g-orange-250:#f5ccb0;--g-orange-200:#fae7d2;--g-orange-100:#fae7d2;--g-orange-75:#f3e3e3;--g-orange-50:#fcfff2;
--g-orange-line:#cc7041;--g-orange-line-soft:#f5ccb0;--g-orange-line-hard:#8f4a39;
--g-signal:#cc7041;--g-signal-deep:#8f4a39;
--g-steel-700:#1d2247;--g-steel-600:#7f8582;--g-steel-500:#a6ada9;--g-steel-400:#bfc7c1;--g-steel-300:#d7e0d9;--g-steel-100:#f3e3e3;--g-steel-200:#e6ece7;--g-motion-fast:120ms ease;

--g-black:#101114;--g-ink:#272829;--g-ink-soft:#3b3d3d;--g-gray-800:#3b3d3d;--g-gray-700:#585c5b;--g-gray-500:#7f8582;--g-gray-400:#a6ada9;--g-gray-300:#bfc7c1;--g-gray-200:#d7e0d9;--g-gray-125:#f3e3e3;--g-gray-100:#f3e3e3;--g-gray-50:#fcfff2;--g-white:#fcfff2;
--g-danger:#991f2f;--g-danger-deep:#5c1a33;--g-danger-ink:#991f2f;--g-danger-bg:#f3e3e3;--g-danger-bg-soft:#f5ccb0;--g-danger-line:#e53737;
--g-success:#227a2e;--g-success-deep:#1d522b;--g-success-ink:#1d522b;--g-success-bg:#f7fac8;
--g-warn-bg:#f5db93;--g-warn-bg-alt:#f7fac8;--g-warn-ink:#52321d;--g-warn-line:#b88c33;
--g-focus:#313199;--g-focus-alt:#33408f;
--g-link:#1d3c66;--g-link-hashtag:#28628f;--g-link-hashtag-hover:#1d3c66;--g-link-mention:#8f4a39;--g-link-mention-hover:#52321d;--g-link-blog:#28628f;
--g-ph-avatar:#a6ada9;--g-ph-photo:#bfc7c1;--g-ph-portrait:#f5ccb0;--g-ph-portrait-ink:#52321d;
--g-dark-900:#101114;--g-dark-800:#16272c;--g-dark-700:#272829;--g-dark-600:#3b3d3d;--g-dark-line:#3b3d3d;--g-dark-ink:#fcfff2;--g-dark-ink-soft:#d7e0d9;--g-dark-ink-mute:#bfc7c1;
--g-discord:#543fe0;

/* ---- Surfaces ---- */
--g-surface-canvas:#1d3c66;--g-surface-shell:#fcfff2;--g-surface-panel:#fcfff2;
--g-surface-post:#fcfff2;--g-surface-elevated:#fae7d2;--g-surface-inset:#d7e0d9;
/* ---- Text ---- */
--g-text-primary:#101114;--g-text-canvas:#fcfff2;--g-text-secondary:#3b3d3d;
--g-text-muted:#585c5b;--g-text-inverse:#fcfff2;--g-text-heading:#8f4a39;
/* ---- Links and focus ---- */
--g-link-text:#1d3c66;--g-link-hover:#8f4a39;--g-link-visited:#8f3370;--g-focus-ring:#313199;
/* ---- Borders ---- */
--g-border-default:#cc7041;--g-border-subtle:#f5ccb0;--g-border-strong:#8f4a39;
/* ---- Header and navigation ---- */
--g-header-surface:#28628f;--g-header-text:#fcfff2;
--g-nav-surface:#1d3c66;--g-nav-text:#fcfff2;--g-nav-activeSurface:#f5be6c;--g-nav-activeText:#52321d;
/* ---- Profile identity ---- */
--g-identity-surface:#28628f;--g-identity-text:#fcfff2;--g-identity-meta:#d7e0d9;
--g-profile-avatarShape:square;
/* ---- Profile blocks ---- */
--g-block-surface:#fcfff2;--g-block-headerSurface:#f5be6c;--g-block-headerText:#52321d;
/* ---- Posts ---- */
--g-post-surface:#fcfff2;--g-post-headerSurface:#fae7d2;--g-post-text:#101114;--g-post-muted:#585c5b;
--g-post-mediaMat:#101114;--g-post-border:#cc7041;
--g-post-actionSurface:#fae7d2;--g-post-actionText:#52321d;--g-post-actionActive:#991f2f;
--g-post-quoteSurface:#d7e0d9;--g-post-commentSurface:#f3e3e3;--g-post-menuSurface:#fcfff2;
/* ---- Inputs ---- */
--g-input-surface:#fcfff2;--g-input-text:#101114;--g-input-placeholder:#585c5b;--g-input-border:#8f4a39;
/* ---- Buttons ---- */
--g-button-surface:#f5be6c;--g-button-text:#52321d;--g-button-border:#8f4a39;--g-button-hover:#f5db93;
--g-button-active:#eb9b54;--g-button-activeText:#33211b;--g-button-disabled:#bfc7c1;--g-button-disabledText:#585c5b;
/* ---- Tables and lists ---- */
--g-table-labelSurface:#fae7d2;--g-table-valueSurface:#fcfff2;--g-table-border:#f5ccb0;
--g-list-divider:#f5ccb0;--g-list-hover:#fae7d2;
/* ---- Media ---- */
--g-media-tileSurface:#fae7d2;--g-media-tileBorder:#cc7041;
--g-media-captionSurface:#101114;--g-media-captionText:#fcfff2;--g-media-objectFit:cover;
/* ---- Disclosures ---- */
--g-disclosure-surface:#fae7d2;--g-disclosure-text:#52321d;
/* ---- Polls and progress ---- */
--g-poll-track:#f5ccb0;--g-poll-fill:#eb9b54;--g-poll-mine:#8f4a39;
--g-progress-track:#f5ccb0;--g-progress-fill:#eb9b54;--g-progress-stripes:repeating-linear-gradient(90deg,#eb9b54 0 4px,color-mix(in srgb,#eb9b54 82%,black) 4px 8px);--g-countdown-number:#8f4a39;
/* ---- Now Playing ---- */
--g-playlist-stage:#101114;--g-playlist-control:#f5be6c;--g-playlist-active:#eb9b54;
/* ---- Social blocks ---- */
--g-social-surface:#d7e0d9;--g-social-header:#1d3c66;--g-social-text:#101114;--g-social-border:#28628f;
/* ---- Geometry ---- */
--g-geometry-borderWidth:1px;--g-geometry-cornerRadius:0px;--g-geometry-sectionGap:10px;--g-geometry-shadowPanel:none;
/* ---- Typography ---- */
--g-typography-bodyFont:Verdana,Arial,sans-serif;--g-typography-headingFont:Verdana,Arial,sans-serif;
--g-family-ui:Verdana,Arial,Helvetica,sans-serif;--g-family-display:Arial,Helvetica,sans-serif;
--g-family-serif:Georgia,'Times New Roman',serif;--g-family-mono:ui-monospace,Menlo,Consolas,monospace;
/* ---- Canvas / cursor ---- */
--g-canvas-pattern:none;--g-canvas-repeat:repeat;--g-canvas-position:top left;--g-canvas-pattern-image:none;--g-canvas-pattern-size:12px 12px;
--g-cursor-style:default;--g-profile-avatarRadius:0;
/* Uploaded background and cursor. The stored tokens are bare paths; the two
   *Layer/--g-cursor values are the url() forms composer_theme_derived_vars()
   builds from them, defaulted here so an unthemed page still resolves. */
--g-canvas-image:;--g-cursor-image:;--g-canvas-imageLayer:none;--g-cursor:default;
/* Set to transparent by composer_theme_derived_vars() when the canvas has an
   image or pattern; "initial" leaves the shell and #content their surfaces. */
--g-canvas-clear:initial;

/* ---- Fixed layout widths — widened per the redux (was 800px) ---- */
--g-w-shell:900px;--g-w-feed:560px;--g-w-side:300px;--g-w-prof-left:305px;--g-w-prof-right:565px;--g-gutter-shell:10px;--g-gap-col:20px;

/* ---- Win98 tri-tone bevels (98.css technique). Kept here as reference/
   documentation ONLY — do NOT use var(--g-bevel98-raised) etc. directly.
   A custom property that itself contains var() references to other custom
   properties gets those references substituted ONCE, at whichever element
   first declares it (here, :root) — the result inherits down as a frozen
   value, it is not re-resolved per descendant. Concretely: a themed
   profile (body.profile-theme-v2, or the Theme Studio's live preview,
   which override --g-surface-elevated/--g-border-strong/--g-button-*
   scoped to a subtree) would still render bevels in the SITE DEFAULT
   colours, not the theme's own palette, if a rule used
   box-shadow:var(--g-bevel98-raised). Confirmed empirically (Chromium):
   var() chained through an intermediate custom property does not
   re-theme; var() used directly in the consuming property does. So every
   actual consumer below inlines the four-layer recipe with DIRECT
   var(--g-surface-elevated) / var(--g-border-strong) / var(--g-button-*)
   references instead of going through --g-bevel98-*. If you add a new
   beveled element, copy the inline recipe from an existing rule (e.g.
   .g-bevel below) — do not reach for var(--g-bevel98-raised). ---- */
--g-bevel98-raised:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border);
--g-bevel98-sunken:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border);
--g-bevel98-raised-thick:inset 2px 2px 0 var(--g-surface-elevated),inset -2px -2px 0 var(--g-border-strong),inset 3px 3px 0 var(--g-button-surface),inset -3px -3px 0 var(--g-button-border);
--g-bevel98-sunken-thick:inset -2px -2px 0 var(--g-surface-elevated),inset 2px 2px 0 var(--g-border-strong),inset -3px -3px 0 var(--g-button-surface),inset 3px 3px 0 var(--g-button-border);
--g-bevel98-disabled:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-gray-300,#bfc7c1),inset 2px 2px 0 var(--g-button-disabled),inset -2px -2px 0 var(--g-gray-300,#bfc7c1);
--g-bevel98-field:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-input-surface),inset 2px 2px 0 var(--g-input-border);
--g-bevel98-window:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-surface-panel),inset -2px -2px 0 var(--g-border-default);
--g-focus-outline:2px solid var(--g-focus-ring);--g-focus-offset:1px;

/* ---- 98.css scrollbar recipe (used on scrollable modules) ---- */
--g-scroll-track:var(--g-surface-inset);--g-scroll-face:var(--g-surface-shell);

/* ---- Legacy surfaces (profile blocks, editor, theme studio) ----
   This site's redux (the tokens above) recolored the sitewide chrome --
   shell, header, nav, boxes, buttons, inputs, tables, post card, swiper --
   but never reached profile blocks (.pb-*), the profile editor, or the
   theme-studio composer chrome, which still hardcode the older, brighter
   pre-redux palette. These tokens don't change that palette -- each one's
   value is exactly the literal it replaces -- they just make it Theme
   Studio-editable going forward instead of a permanent, unthemeable hex. */
--g-legacy-border:#ff9933;--g-legacy-headerBg:#ffcc99;--g-legacy-headerText:#7a3a00;
--g-legacy-accent:#b35900;--g-legacy-muted:#6b6b6b;--g-legacy-link:#003399;
/* Chrome, not per-profile theme: the account menu's hover surface. It has to
   differ from --g-nav-activeSurface, which is the same colour the menu panel
   itself is painted with, so "hovered" and "not hovered" looked identical. */
--g-nav-hoverSurface:#ffd9a3;
--g-legacy-hoverBg:#fff7ec;--g-legacy-avatarBg:#7a8ca3;
--g-legacy-buttonBg:#c9d6e8;--g-legacy-buttonBorder:#9fb6d4;--g-legacy-buttonText:#336;--g-legacy-buttonHoverBg:#d6e1ef;
--g-legacy-headerHoverBg:#ffe0b3;--g-legacy-headerActiveBg:#ffb866;--g-legacy-panelBg:#fff;

/* ---- Admin console (css/admin-triage.css) ----
   A separate dark navy/gold console palette for the staff-only report and
   triage tool -- it never shared a hex with the public site's warm/light
   contract, so it gets its own token family instead of forcing a mismatch.
   Values are exactly the literals they replace. */
--g-admin-bg:#111128;--g-admin-border:#4466aa;--g-admin-borderMuted:#2a2a50;
--g-admin-text:#b0b8d8;--g-admin-textMuted:#8090a8;
--g-admin-accent:#ffd166;--g-admin-accentText:#1a1a2e;--g-admin-link:#7ab8ff;
--g-admin-hoverBg:#252545;--g-admin-hoverText:#ffffff;
--g-admin-danger:#cc2222;--g-admin-neutral:#5c5c72;--g-admin-warn:#ffe080;

/* ---- Search desk (css/tntsearch.css) ----
   The TNTSearch skin's own warm brown/tan palette, separate from the
   site's orange/navy contract. Values are exactly the literals they
   replace. */
--g-search-border:#d3af72;--g-search-kicker:#875114;--g-search-heading:#4c2d0d;--g-search-muted:#66533b;
--g-search-inputBorder:#b88c4e;--g-search-inputBg:#fffdf9;--g-search-inputText:#21160c;
--g-search-buttonBorder:#6e3900;--g-search-buttonBg:#7a4100;--g-search-buttonText:#fffdf7;--g-search-buttonHoverBg:#5c3000;
--g-search-stateBorder:#c99037;--g-search-stateBg:#fff8e7;--g-search-stateText:#5e4b33;--g-search-stateStrong:#54300b;
--g-search-resultHeading:#593000;--g-search-resultMeta:#6b5b47;
--g-search-otherHeading:#6a461d;--g-search-otherPanelHeading:#7a3e00;
--g-search-personLink:#2f4b67;--g-search-dottedBorder:#d9bd8d;--g-search-personHoverBg:#f9edcf;--g-search-smallMuted:#655642;
}

/* Round avatars are handled by the live contract, which emits
   --g-profile-avatarRadius directly (composer_theme_css) and mirrors it in the
   preview via [data-theme-avatar-shape]. A [data-g-avatar] attribute is never
   written by anything, so the selector it used to carry has been removed. */

/* ============================================================
   2. SITEWIDE ACTIVATION — the tokens above now drive the whole
   site by default (redux directive: "Full v2 — retire old
   presets"), not just the opt-in profile-theme-v2 path.
   ============================================================ */
body{background:var(--g-surface-canvas);cursor:var(--g-cursor,var(--g-cursor-style))}
a{color:var(--g-link-text)}
a:hover{color:var(--g-link-hover)}
a:visited{color:var(--g-link-visited)}
:focus-visible{outline:2px solid var(--g-focus-ring);outline-offset:2px}

#shell{width:var(--g-w-shell);background:var(--g-surface-shell);border-left-color:var(--g-surface-shell);border-right-color:var(--g-surface-shell)}
#feedcol{width:var(--g-w-feed)}
#sidecol{width:var(--g-w-side)}
#leftcol{width:var(--g-w-prof-left)}
#rightcol{width:var(--g-w-prof-right)}

#header{background:var(--g-header-surface);border-bottom-color:var(--g-border-strong)}
#header .logo{color:var(--g-header-text)}
#header .logo span{color:var(--g-identity-meta)}
#header .search{color:var(--g-header-text)}
/* Buttons carry their own light surface, so the header's near-white link
   colour must not repaint them: it put #fcfff2 on the Discord button's
   #f5be6c at 1.66:1 -- the primary call to action for logged-out visitors. */
#header .search .auth a:not(.btn),#header .search .auth a:not(.btn):visited{color:var(--g-header-text)!important}

#navbar,#navbar.nav-flat{background:var(--g-nav-surface);color:var(--g-nav-text)}
#navbar a{color:var(--g-nav-text)}
#navbar a:hover{color:var(--g-nav-activeText);background:var(--g-nav-activeSurface);text-decoration:none}
#navbar a.active{color:var(--g-nav-activeText);background:var(--g-nav-activeSurface);font-weight:bold;text-decoration:none}
#navbar a,#navbar a.active{display:inline-flex;align-items:center;min-height:20px;padding:2px 7px}
#navbar .nav-sep{color:var(--g-nav-text);opacity:.5}

/* ---- boxes / bands ---- */
.box .hd{background:var(--g-block-headerSurface);border:var(--g-geometry-borderWidth) solid var(--g-border-strong);border-bottom:0;color:var(--g-block-headerText)}
.box .bd{border:var(--g-geometry-borderWidth) solid var(--g-border-default);background:var(--g-surface-panel);color:var(--g-text-primary)}
/* --g-band-bg was a v1 leftover that Theme Contract v2 never emits, so this
   always fell through to the fallback anyway. Both halves now name tokens the
   Theme Studio actually offers (Foundation → border.strong, Sections & text →
   text.inverse), which is what makes the band themeable at all. */
.band{background:var(--g-border-strong);color:var(--g-text-inverse)}
.stories{border-color:var(--g-border-default);background:var(--g-surface-panel)}
.miniprof{border-color:var(--g-border-default);background:var(--g-surface-panel)}
.blogtitle{color:var(--g-text-heading)}
.blogbody a{color:var(--g-link-blog)}
.blogbody blockquote{border-left-color:var(--g-border-default);background:var(--g-surface-elevated);color:var(--g-text-secondary)}
.bulletin{border-color:var(--g-border-default);background:var(--g-surface-panel)}
table.info caption{background:var(--g-header-surface);color:var(--g-header-text);border-color:var(--g-border-strong)}
table.info th,table.info td{border-color:var(--g-border-default)}
table.info th{background:var(--g-table-labelSurface);color:var(--g-text-heading)}
table.comments td{border-color:var(--g-border-default)}
table.comments td.who{background:var(--g-surface-elevated)}
.notiflist li.unseen{background:var(--g-list-hover);border-left-color:var(--g-border-default)}
.bloglist li,.sugg li{border-bottom-color:var(--g-border-subtle)}
.taglist li{border-bottom-color:var(--g-border-subtle)}
.taglist .hashtag{color:var(--g-link-hashtag)}
.taglist .hashtag:hover{color:var(--g-link-hashtag-hover)}
a.hashtag{color:var(--g-link-hashtag)}
a.hashtag:hover{color:var(--g-link-hashtag-hover)}
.flash{background:var(--g-warn-bg);border-color:var(--g-border-default);color:var(--g-warn-ink)}
.online{color:var(--g-signal-deep)}
.friendcount b{color:var(--g-danger)}
.commentcount b{color:var(--g-danger)}
.delwall{color:var(--g-danger)}
.charcnt.warn{color:var(--g-orange-700)}
.charcnt.over{color:var(--g-danger)}
.notif-badge{background:var(--g-danger)}
#bannerad{border-top-color:var(--g-border-subtle)}
#bannerad .adlabel{color:var(--g-text-muted)}
#footer{border-top-color:var(--g-border-subtle);color:var(--g-text-muted)}
.prof-tabs .ptab:hover{background:var(--g-table-labelSurface)}
.prof-tabs .ptab.on{background:var(--g-surface-shell);color:var(--g-text-primary)}
.dots-drop,.repost-drop{background:var(--g-post-menuSurface);border-color:var(--g-border-default)}
.dots-drop a,.repost-drop a,.dots-drop button,.repost-drop button{color:var(--g-link-text);border-bottom-color:var(--g-border-subtle)}
.dots-drop a:hover,.repost-drop a:hover,.dots-drop button:hover,.repost-drop button:hover{background:var(--g-list-hover)}
.dots-drop a.danger,.dots-drop button.danger{color:var(--g-danger)}
.story .ring{background:var(--g-signal)}
.story.seen .ring{background:var(--g-steel-400)}
.pgthumb{background:var(--g-surface-elevated);border-color:var(--g-border-default)}
.pgthumb:hover{border-color:var(--g-border-strong)}
.ac-drop{background:var(--g-nav-surface);border-color:var(--g-border-default)}
.ac-drop li:hover,.ac-drop li.ac-sel{background:var(--g-navy-800);color:var(--g-nav-activeSurface)}

/* ============================================================
   3. WIN98 BEVEL — every button family loses the single-colour
   outset border and gains the literal tri-tone box-shadow.
   Colour is owned entirely here; nothing above sets it inline.
   ============================================================ */
.btn,.bigbtn,a.bigbtn-inline,.pact,.mp-btn,.pnl-tools .tool,
input[type=submit],input[type=button],input[type=reset],
.searchform input[type=submit],#header .search .headsearch input[type=submit],.th-preset button,
.gallery .swiper-button-next,.gallery .swiper-button-prev,
#lb-prev,#lb-next,.crop-icon-button,.composer-theme-convert,
.composer-block-tools button,.composer-inspector-tabs button{
  background:var(--g-button-surface);color:var(--g-button-text);
  border:0;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border);border-radius:var(--g-geometry-cornerRadius);
  cursor:pointer;
}
.btn:hover:not(:disabled),.bigbtn:hover,a.bigbtn-inline:hover,.pact:hover,.mp-btn:hover,
.pnl-tools .tool:hover,
input[type=submit]:hover,input[type=button]:hover,
.searchform input[type=submit]:hover,
.gallery .swiper-button-next:hover,.gallery .swiper-button-prev:hover{
  background:var(--g-button-hover);
}
.btn:active,.bigbtn:active,a.bigbtn-inline:active,.pact:active,.pact.on,.mp-btn:active,
.pnl-tools .tool:active,.pnl-tools .tool.on,
input[type=submit]:active,input[type=button]:active,
.searchform input[type=submit]:active,
.gallery .swiper-button-next:active,.gallery .swiper-button-prev:active,
#lb-prev:active,#lb-next:active{
  box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border);background:var(--g-button-active);color:var(--g-button-activeText);
  border-style:solid;
}
.btn.busy{background:var(--g-border-strong);color:var(--g-text-inverse);box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border)}
.btn:disabled,input[type=submit]:disabled{background:var(--g-button-disabled);color:var(--g-button-disabledText);border:0;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-gray-300,#bfc7c1),inset 2px 2px 0 var(--g-button-disabled),inset -2px -2px 0 var(--g-gray-300,#bfc7c1);cursor:default}
.btn:disabled:active{box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-gray-300,#bfc7c1),inset 2px 2px 0 var(--g-button-disabled),inset -2px -2px 0 var(--g-gray-300,#bfc7c1)}
/* "Big"/primary emphasis gets the thicker 2px reading edge */
.bigbtn,a.bigbtn-inline,.pact-primary,.searchform input[type=submit]{box-shadow:inset 2px 2px 0 var(--g-surface-elevated),inset -2px -2px 0 var(--g-border-strong),inset 3px 3px 0 var(--g-button-surface),inset -3px -3px 0 var(--g-button-border)}
.bigbtn:active,a.bigbtn-inline:active,.pact-primary:active,.pact-primary.on{box-shadow:inset -2px -2px 0 var(--g-surface-elevated),inset 2px 2px 0 var(--g-border-strong),inset -3px -3px 0 var(--g-button-surface),inset 3px 3px 0 var(--g-button-border)}
/* Secondary/"plain" family (steel) keeps a visibly cooler face than primary */
.btn.plain{background:var(--g-steel-300);color:var(--g-nav-surface);box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border)}
.btn.plain:hover{background:var(--g-steel-200,var(--g-steel-300))}
.btn.plain:active{background:var(--g-steel-400);box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border)}
:is(.btn,.bigbtn,.pact,.mp-btn,input[type=submit],input[type=button]):focus-visible{outline:2px solid var(--g-focus-ring);outline-offset:2px}

/* ---- Sunken 98 fields ---- */
.authform input[type=text],.authform input[type=password],.authform textarea,.authform input[type=file],
#header .search .headsearch input[type=text],.searchform input[type=text],
.cmp-bar input[type=text],.reply-box .addc input[type=text],.post .addc input[type=text],
form.addc input[type=text],form.addc textarea,#global-search{
  background:var(--g-input-surface);color:var(--g-input-text);
  border:0;box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-input-surface),inset 2px 2px 0 var(--g-input-border);padding:4px;
}
.authform input[type=text]:focus-visible,.authform textarea:focus-visible,
#global-search:focus-visible,.searchform input[type=text]:focus-visible,
.cmp-bar input[type=text]:focus-visible,form.addc input[type=text]:focus-visible{
  outline:2px solid var(--g-focus-ring);outline-offset:1px;
}
.authform label{color:var(--g-text-heading)}

/* ============================================================
   4. SCROLLBAR — 98.css dithered scrollbar utility, for any
   internal scroller (profile post box, long module bodies).
   ============================================================ */
.g-scroll98{scrollbar-color:var(--g-border-strong) var(--g-surface-inset);scrollbar-width:auto}
.g-scroll98::-webkit-scrollbar{width:17px;height:17px}
.g-scroll98::-webkit-scrollbar-track{background-color:var(--g-surface-inset);background-image:repeating-conic-gradient(var(--g-surface-shell) 0% 25%,var(--g-surface-inset) 0% 50%);background-size:2px 2px}
.g-scroll98::-webkit-scrollbar-thumb{background:var(--g-border-strong);box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border)}
.g-scroll98::-webkit-scrollbar-thumb:active{background:var(--g-button-active);box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border)}
.g-scroll98::-webkit-scrollbar-corner{background:var(--g-surface-inset)}

/* ============================================================
   5. POST CARD — carry the Theme Contract outward. post-card-
   refresh.css sets --pc-* to literal v2 hex unconditionally and
   only reads --g-post-* inside the opt-in .theme-v2 scope; this
   makes every .post everywhere (home feed, blog comments, a
   profile that never opted into Theme Studio) read the v3
   contract by default, same specificity, later in the cascade.
   ============================================================ */
.post{
  --pc-surface:var(--g-post-surface,#fcfff2);
  --pc-header:var(--g-post-headerSurface,#fae7d2);
  --pc-text:var(--g-post-text,#101114);
  --pc-muted:var(--g-post-muted,#585c5b);
  --pc-link:var(--g-link-text,#1d3c66);
  --pc-link-hover:var(--g-link-hover,#8f4a39);
  --pc-border:var(--g-post-border,#cc7041);
  --pc-subtle-border:var(--g-border-subtle,#f5ccb0);
  --pc-media:var(--g-post-mediaMat,#101114);
  --pc-action-surface:var(--g-post-actionSurface,#fae7d2);
  --pc-action-text:var(--g-post-actionText,#52321d);
  --pc-action-active:var(--g-post-actionActive,#991f2f);
  --pc-action-hover:var(--g-button-hover,#f5db93);
  --pc-quote:var(--g-post-quoteSurface,#d7e0d9);
  --pc-comment:var(--g-post-commentSurface,#f3e3e3);
  --pc-menu:var(--g-post-menuSurface,#fcfff2);
  --pc-input:var(--g-input-surface,#fcfff2);
  --pc-input-text:var(--g-input-text,#101114);
  --pc-input-border:var(--g-input-border,#8f4a39);
  --pc-focus:var(--g-focus-ring,#313199);
  --pc-inset:12px;
  --pc-inset-compact:9px;
}
/* Post action buttons pick up the bevel too. The redux gave them 36px rows and
   16px icons for weight, which made a row of four read as the loudest thing on
   a card whose subject is a photo. Back to 26px rows and 14px icons: still a
   comfortably-above-24px pointer target, still beveled, no longer competing
   with the post. */
.post .acts{gap:6px;min-height:auto;padding:5px var(--pc-inset)}
.post .acts .ico,.post .acts .repost-caret{
  background:var(--g-button-surface);color:var(--g-button-text);
  border:0;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border);
  min-height:26px;padding:4px 8px;gap:5px;font-size:11px;
}
/* Repost and its caret sit in an inline-flex wrapper that defaults to
   align-items:stretch, so the pair grew to the wrapper's height and stood
   proud of the three buttons beside them. */
.post .acts .repost-wrap{align-items:center}
.post .acts .pxi{width:14px;height:14px;flex-basis:14px}
.post .acts .ico:hover:not([disabled]){background:var(--g-button-hover)}
.post .acts .ico:active:not([disabled]),.post .acts .ico[aria-pressed="true"]:not([disabled]),
.post .acts .liked,.post .acts .saved,.post .acts .reposted{
  box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border);background:var(--g-button-active);color:var(--g-button-activeText);
}
/* Counts take their button's own label colour. They used to be set back in
   --pc-muted-strong, which read --g-post-mutedStrong: a token this file
   declares at :root but that the server contract has no member for (the post
   family stops at post.muted, see composer_theme_token_definitions). Theme
   Studio therefore could never override it, so every themed profile kept the
   :root #3b3d3d -- fine on the default peach at 6.5:1, invisible on a dark
   profile at 1.5:1. Mapping it to post.muted themes correctly but drops the
   default theme to 4.0:1, under AA, so the set-back look is what goes.
   inherit is legible in every theme by construction, and is what the pressed
   state already did. */
.post .acts .likecount,.post .acts b{color:inherit;font-weight:bold;font-variant-numeric:tabular-nums}
.post .acts .ico:is(:active,[aria-pressed="true"]) b,
.post .acts .liked b,.post .acts .saved b,.post .acts .reposted b{color:inherit}
.post .acts .repost-caret{padding:4px 5px;margin-left:2px}
/* tabular-nums (above) keeps digits equal-width within a number, but a
   1-digit and a 3-digit count are still different total widths unless the
   count itself reserves fixed space -- without this, hitting 10 likes or
   100 reposts resized the button same as the label-text swap below did. */
.post .acts .likecount,.post .acts .repostcount,.post .acts .replycount{display:inline-block;min-width:3ch;text-align:center}
/* Reserve enough width for each button's longer state (label text changes
   Like<->Liked / Repost<->Reposted, plus a count appearing) so pressing it
   doesn't visibly resize the button and shove its neighbours sideways.
   Sized to the longest common case (up to a 3-digit count, per the fixed
   count width above); a genuinely large count is rare and allowed to grow
   past this floor rather than clip. */
.post .acts .reply-btn{min-width:88px}
.post .acts .likebtn{min-width:90px}
.post .acts .repost-btn{min-width:114px}
.post .cmts .c,.post .acts .ico{font-size:12px}
.post .acts .ico:focus-visible,.post .acts .repost-caret:focus-visible{outline:2px solid var(--g-focus-ring);outline-offset:2px}

/* ============================================================
   6. CHROME ICONS — window controls, disclosure, search, loading.
   Separate vocabulary from the posting-UI .pxi set (pixel-posting-
   icons.css): mask-image on images/ui/chrome-icons/, same technique.
   ============================================================ */
.gic{
  display:inline-block;width:14px;height:14px;flex:0 0 14px;vertical-align:-2px;
  background-color:currentColor;background-repeat:no-repeat;background-position:center;background-size:100% 100%;
  image-rendering:pixelated;
  -webkit-mask-repeat:no-repeat;-webkit-mask-position:center;-webkit-mask-size:contain;
  mask-repeat:no-repeat;mask-position:center;mask-size:contain;
}
.gic-close{-webkit-mask-image:url('../images/ui/chrome-icons/close.svg');mask-image:url('../images/ui/chrome-icons/close.svg')}
.gic-spinner{-webkit-mask-image:url('../images/ui/chrome-icons/spinner.svg');mask-image:url('../images/ui/chrome-icons/spinner.svg')}
.gic-chevron-up{-webkit-mask-image:url('../images/ui/chrome-icons/chevron-up.svg');mask-image:url('../images/ui/chrome-icons/chevron-up.svg')}
.gic-chevron-down{-webkit-mask-image:url('../images/ui/chrome-icons/chevron-down.svg');mask-image:url('../images/ui/chrome-icons/chevron-down.svg')}
.gic-search{-webkit-mask-image:url('../images/ui/chrome-icons/search.svg');mask-image:url('../images/ui/chrome-icons/search.svg')}
.gic-cog{-webkit-mask-image:url('../images/ui/chrome-icons/cog.svg');mask-image:url('../images/ui/chrome-icons/cog.svg')}
.gic-spin{animation:g-spin 1s linear infinite}
@keyframes g-spin{from{transform:rotate(0)}to{transform:rotate(359deg)}}
@media (forced-colors:active){.gic{background-color:ButtonText}}

/* ============================================================
   7. PAGINATION — numbered pager (includes/pagination.php) and the
   AJAX "Load more" button (js/app.js loadMore(), #load_more_btn).
   ============================================================ */
.g-pager{display:flex;align-items:center;justify-content:center;gap:6px;flex-wrap:wrap;margin:12px 0;padding:6px 0}
.g-pager-nav{display:inline-flex;align-items:center;gap:5px}
.g-pager-nav[aria-disabled="true"]{background:var(--g-button-disabled);color:var(--g-button-disabledText);box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-gray-300,#bfc7c1),inset 2px 2px 0 var(--g-button-disabled),inset -2px -2px 0 var(--g-gray-300,#bfc7c1);cursor:default}
.g-pager-nav .gic{background-color:currentColor}
.g-pager-nums{display:inline-flex;align-items:center;gap:3px}
.g-pager-num{min-width:26px;text-align:center;padding:3px 6px}
.g-pager-current{background:var(--g-button-active);color:var(--g-button-activeText);box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border)}
.g-pager-ellipsis{padding:0 3px;color:var(--g-text-muted)}

/* AJAX "Load more" — chevron leads the label per the redux review. */
.loadmore-wrap{text-align:center;margin:10px 0}
.bigbtn.loadmore,#load_more_btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;width:auto;min-width:160px}
.bigbtn.loadmore::before,#load_more_btn::before{content:"";display:inline-block;width:12px;height:12px;background-color:currentColor;-webkit-mask:url('../images/ui/chrome-icons/chevron-down.svg') center/contain no-repeat;mask:url('../images/ui/chrome-icons/chevron-down.svg') center/contain no-repeat}
.bigbtn.loadmore:disabled::before,#load_more_btn:disabled::before{animation:g-spin 1s linear infinite;-webkit-mask-image:url('../images/ui/chrome-icons/spinner.svg');mask-image:url('../images/ui/chrome-icons/spinner.svg')}
.bigbtn.loadmore.loadmore-retry::before,#load_more_btn.loadmore-retry::before{-webkit-mask-image:url('../images/ui/chrome-icons/close.svg');mask-image:url('../images/ui/chrome-icons/close.svg')}

/* ---- Profile: identity header, blocks, pinned post, post-box scrollbar ---- */
.prof-head{box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-surface-panel),inset -2px -2px 0 var(--g-border-default);background:var(--g-surface-panel);border:0;padding:14px}
.prof-name{color:var(--g-text-heading)}
.prof-handle,.blogcard-t,.g-explore-people .nm a{overflow-wrap:anywhere}
.pblock{box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-surface-panel),inset -2px -2px 0 var(--g-border-default);background:var(--g-block-surface);border:0}
.pb-hd{background:var(--g-block-headerSurface);color:var(--g-block-headerText);border:0}
.pb-hd-x,.pb-hd-x a{color:inherit}
.pb-bar i{background:var(--g-progress-stripes)}
.post-pinflag{margin-bottom:0;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border);background:var(--g-button-surface)}
.post-pinflag .pinned-badge{display:flex;background:none;border:0;align-items:center;gap:5px;padding:4px 8px;font:bold 10px Arial,sans-serif;color:var(--g-button-text);text-transform:uppercase;letter-spacing:.04em}
.post-pinflag+.post{border-top:0}
.profile-posts,.profile-rail-row .profile-post-panel .profile-posts{scrollbar-color:var(--g-border-strong) var(--g-surface-inset)!important}
.profile-posts::-webkit-scrollbar,.profile-rail-row .profile-post-panel .profile-posts::-webkit-scrollbar{width:17px}
.profile-posts::-webkit-scrollbar-track,.profile-rail-row .profile-post-panel .profile-posts::-webkit-scrollbar-track{background-color:var(--g-surface-inset);background-image:repeating-conic-gradient(var(--g-surface-shell) 0% 25%,var(--g-surface-inset) 0% 50%);background-size:2px 2px}
.profile-posts::-webkit-scrollbar-thumb,.profile-rail-row .profile-post-panel .profile-posts::-webkit-scrollbar-thumb{background:var(--g-border-strong);box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border)}
.profile-post-panel,.profile-rail-row .profile-post-panel{border:0!important;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-surface-panel),inset -2px -2px 0 var(--g-border-default);background:var(--g-surface-panel)!important}

/* ---- Blog index/detail ---- */
.tagchip{display:inline-block;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border);background:var(--g-button-surface);color:var(--g-button-text);padding:2px 7px;font-size:10px;margin:0 4px 4px 0}
.tagchip:hover{background:var(--g-button-hover);color:var(--g-button-text);text-decoration:none}
/* Blog index cards and rail blocks use the same semantic contract as profile content. */
#content.blogsindex .crumbs,#content.blogsindex .pb-sub,#content.blogsindex .blogcard-meta,#content.blogsindex .blogcard-counts,#content.blogsindex .empty-state{color:var(--g-text-muted)}
#content.blogsindex .blogcard{border:var(--g-geometry-borderWidth) solid var(--g-post-border);background:var(--g-post-surface);color:var(--g-post-text);padding:12px}
#content.blogsindex .blogcard-av,#content.blogsindex .pb-wallav{background:var(--g-media-tileSurface);border-color:var(--g-media-tileBorder)}
#content.blogsindex .blogcard-x{color:var(--g-post-text)}
#content.blogsindex a.blogcard-t,#content.blogsindex a.blogcard-t:visited{color:var(--g-text-heading);font:italic bold 16px/1.25 Georgia, serif}
#content.blogsindex a.blogcard-t:hover,#content.blogsindex a.blogcard-t:focus-visible{color:var(--g-link-hover)}
#content.blogsindex .tagchip,#content.blogsindex .tagchip:visited{color:var(--g-button-text)}
#content.blogsindex .pblock .pb-bd{background:var(--g-block-surface);border:0;color:var(--g-text-primary)}
#content.blogsindex .pb-list li,#content.blogsindex .pb-wallrow{border-bottom-color:var(--g-list-divider)}
#content.blogsindex .empty-state a:not(.bigbtn-inline){color:var(--g-link-text)}
#content.blogsindex .empty-state a:not(.bigbtn-inline):hover,#content.blogsindex .empty-state a:not(.bigbtn-inline):focus-visible{color:var(--g-link-hover)}
.prof-tabs{background:var(--g-nav-surface);border-color:var(--g-border-default)}
.prof-tabs .ptab{background:var(--g-nav-surface);border-color:var(--g-border-default);color:var(--g-nav-text)}
.prof-tabs .ptab.on,.prof-tabs .ptab:hover{background:var(--g-nav-activeSurface);border-color:var(--g-border-default);color:var(--g-nav-activeText)}
/* Profile feed components retain semantic theme tokens inside the legacy rail layout. */
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel{background:var(--g-block-surface)!important;color:var(--g-text-primary)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-tabs .ptab{background:var(--g-nav-surface);border-color:var(--g-border-default);color:var(--g-nav-text)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-tabs .ptab.on,:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-tabs .ptab:hover{background:var(--g-nav-activeSurface);border-color:var(--g-border-default);color:var(--g-nav-activeText)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-composer{background:var(--g-post-surface);border-color:var(--g-post-border);color:var(--g-post-text)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-composer:hover{background:var(--g-post-surface)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .pc-av{background:var(--g-media-tileSurface);border-color:var(--g-media-tileBorder)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .pc-fld{background:var(--g-input-surface);border-color:var(--g-input-border);color:var(--g-input-placeholder)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .pc-btn{background:var(--g-button-surface);border:0;color:var(--g-button-text);box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-composer:hover .pc-btn{background:var(--g-button-hover)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-composer:active .pc-btn{background:var(--g-button-active);color:var(--g-button-activeText);box-shadow:inset -1px -1px 0 var(--g-surface-elevated),inset 1px 1px 0 var(--g-border-strong),inset -2px -2px 0 var(--g-button-surface),inset 2px 2px 0 var(--g-button-border)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .prof-composer:focus-visible{outline:2px solid var(--g-focus-ring);outline-offset:2px}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .profile-posts,:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .profile-posts>.loadmore-wrap{background:var(--g-post-surface);border-color:var(--g-post-border);color:var(--g-post-text)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .profile-posts>.post{background:var(--g-post-surface);border-color:var(--g-post-border);color:var(--g-post-text)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .profile-posts>.post .top{background:var(--g-post-headerSurface);border-color:var(--g-post-border);color:var(--g-post-text)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .empty-state{color:var(--g-text-muted)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .empty-state a:not(.bigbtn-inline){color:var(--g-link-text)}
:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .empty-state a:not(.bigbtn-inline):hover,:is(#content,#composer-canvas-page).profilepage .profile-rail-row .profile-post-panel .empty-state a:not(.bigbtn-inline):focus-visible{color:var(--g-link-hover)}

/* ---- Explore page ---- */
.g-explore-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;padding:10px 0}
.g-explore-tile{display:block;aspect-ratio:1;border:var(--g-geometry-borderWidth) solid var(--g-border-default);background:var(--g-ph-photo);overflow:hidden}
.g-explore-tile img{width:100%;height:100%;object-fit:cover;display:block;transition:opacity var(--g-motion-fast)}
.g-explore-tile:hover img{opacity:.82}
.g-explore-people{padding:6px 0}
.g-explore-tags{display:flex;flex-wrap:wrap;gap:8px;padding:10px 0}
.g-tag-chip{display:inline-flex;align-items:center;gap:6px;box-shadow:inset 1px 1px 0 var(--g-surface-elevated),inset -1px -1px 0 var(--g-border-strong),inset 2px 2px 0 var(--g-button-surface),inset -2px -2px 0 var(--g-button-border);background:var(--g-surface-elevated);color:var(--g-block-headerText);padding:6px 10px;font-size:11px}
.g-tag-chip:hover{background:var(--g-button-hover);text-decoration:none}
.g-tag-chip span{color:var(--g-text-muted);font-weight:bold}
@media (max-width:620px){.g-explore-grid{grid-template-columns:repeat(3,1fr)}}

/* ---- Discord mark — third-party brand, plain <img>, not masked ---- */
.g-discord-mark{width:14px;height:14px;vertical-align:-2px;margin-right:5px;filter:brightness(0) saturate(100%)}
.g-discord-btn{display:inline-flex;align-items:center;padding:3px 9px;font:bold 10px Verdana,sans-serif;text-decoration:none!important}
.g-discord-btn .g-discord-mark{filter:none}
#header .search .auth{display:flex;align-items:center;justify-content:flex-end;gap:6px}

/* ---- Sidebar Discord widget + ad slot ---- */
.g-discord-widget .hd{display:flex;align-items:center}
.g-discord-widget .hd .g-discord-mark{filter:none}
.g-discord-status{font-size:10px;color:var(--g-text-muted)}
.g-discord-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--g-success);margin-right:4px}
.g-sidead{text-align:center}
.g-sidead .adlabel{font-size:11px;color:var(--g-text-muted);display:block;margin-bottom:4px}
.g-sidead-slot{width:300px;height:250px;margin:0 auto;display:flex;align-items:center;justify-content:center;background:var(--g-surface-inset);border:1px dashed var(--g-border-default);color:var(--g-text-muted);font-size:11px}

@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

@media (max-width:920px){
  #shell{width:100%;max-width:900px}
}

/* ============================================================
   8. MOBILE COLUMN RESET — narrow-viewport override for the
   fixed-width columns above (gobstagram.css's legacy floats and
   this file's own --g-w-feed/--g-w-side/--g-w-prof-* widths).
   Loaded after both, so it wins the cascade at <=620px without
   needing !important. Do NOT reach for overflow-x:hidden instead
   of this — that hides content, it doesn't fix the layout.
   ============================================================ */
@media (max-width: 620px) {
  #shell {
    width: 100%;
    max-width: none;
    border-left-width: 0;
    border-right-width: 0;
  }

  #content {
    padding: 8px 6px;
    min-width: 0;
    box-sizing: border-box;
  }

  #feedcol,
  #sidecol,
  #leftcol,
  #rightcol {
    float: none;
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }

  #sidecol {
    margin-top: 12px;
  }

  .post,
  .gallery,
  .post-swiper,
  .post-swiper .swiper-slide,
  .gallery .swiper-pagination,
  .prof-composer,
  .feed-tabs,
  #compose,
  .cmp-bar,
  .prof-body,
  .prof-feed,
  .prof-rail {
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
  }

  .prof-body {
    flex-wrap: wrap;
  }

  .prof-feed,
  .prof-rail {
    width: 100%;
  }

  .post .cap,
  .post .top,
  .post .acts,
  .post .cmts,
  .post .addc {
    min-width: 0;
    overflow-wrap: anywhere;
  }
}

/* ---- Step 1.2: header stacks instead of packing into one row ---- */
@media (max-width: 620px) {
  #header {
    padding: 8px;
  }

  #header .logo,
  #header .search {
    float: none;
    width: 100%;
    box-sizing: border-box;
  }

  #header .search {
    padding-top: 8px;
    text-align: left;
  }

  #header .search .headsearch {
    display: flex;
    gap: 6px;
    align-items: center;
  }

  #header .search .headsearch input[type="text"] {
    width: auto;
    min-width: 0;
    flex: 1 1 auto;
  }

  #navbar {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 4px;
  }

  #navbar .nav-sep {
    display: none;
  }
}

/* ---- Step 1.3: media obeys the available width instead of spilling ---- */
@media (max-width: 620px) {
  .gallery img,
  .post img,
  .profilepage img {
    max-width: 100%;
  }
}

/* post-card-refresh.css's own <=540px rule shrinks .post .acts .ico to
   3px/4px padding, but it loads before this file, so our unconditional
   bevel sizing above wins the cascade at every width unless re-scaled
   here — without this, the action row stays desktop-sized on phones. */
@media (max-width:540px){
  .post .acts{gap:4px;padding:6px var(--pc-inset)}
  .post .acts .ico{min-height:32px;padding:6px 7px;gap:4px}
  .post .acts .repost-caret{padding:4px 5px}
  .post .acts .pxi{width:14px;height:14px;flex-basis:14px}
}

/* Links inside running text sat at 1.89:1 against the copy around them,
   which fails WCAG 1.4.1 -- colour was the only thing marking them. An
   underline is the conventional second signal and costs the design nothing
   in prose, where links are rare. Navigation and controls are unaffected. */
#content :is(p, li, .bd, .blogmeta, .pb-wallbody) a:not(.btn):not(.bigbtn):not(.pact){text-decoration:underline}

/* Gallery credit line: title, artist, date added. Only appears when the piece
   carries one of the three.

   No colour of its own. The figcaption already resolves to
   --g-media-captionSurface / --g-media-captionText, which is themeable; setting
   a colour here overrode that with a light-surface token and painted the title
   #18253a on #18253a -- invisible. Emphasis comes from weight, and the
   secondary lines step back with opacity, which holds on any caption surface a
   theme picks. */
.cm-credit{display:flex;flex-direction:column;gap:1px;padding:3px 1px 0;font-size:11px;line-height:1.35}
.cm-credit .cm-title{font-weight:bold}
.cm-credit .cm-artist,.cm-credit .cm-added{opacity:.82}
.cm-credit .cm-added{font-variant-numeric:tabular-nums}

/* ── Section inspector: repeatable rows and read-only field summaries ─────── */

/* Rows with their own Remove and reorder buttons carry a visible number,
   because the buttons announce themselves as "Remove link 3" and until now
   nothing on the screen said which row was 3. */
.composer-repeat-row{align-items:start}
.composer-repeat-n{align-self:center;font:11px/1.6 Verdana,Arial,sans-serif;color:var(--g-legacy-muted);font-variant-numeric:tabular-nums}
.composer-repeat-editor>.pact{margin-top:6px}
.composer-repeat-editor>.pb-sub{margin:4px 0 0}
.composer-repeat-editor .pact[disabled]{opacity:.55;cursor:not-allowed}

/* Fields whose one editor is the Details workspace, shown here so the layout
   can be arranged against real content without a second place to type it. */
.composer-field-summary{display:grid;grid-template-columns:auto minmax(0,1fr);gap:3px 10px;margin:6px 0 8px;font:11px/1.45 Verdana,Arial,sans-serif}
.composer-field-summary dt{color:var(--g-legacy-muted)}
.composer-field-summary dd{margin:0;overflow-wrap:anywhere}
.composer-field-summary dd.is-empty{color:var(--g-legacy-muted);font-style:italic}
@media(max-width:520px){.composer-field-summary{grid-template-columns:1fr;gap:0 0}.composer-field-summary dd{margin:0 0 6px}}

/* Collage and Hero size their rows and let the anchor fill one whole row, so
   once images grew a credit line the credit had nowhere to go: it printed over
   the tile in the row beneath, and the last row's ran off the section. The
   figure divides its row instead -- credit at whatever height it needs, image
   takes the rest. Grid, Masonry, Carousel and Filmstrip size the anchor by
   aspect-ratio, so the figure has always been free to grow and they are
   untouched. */
.composer-media-block.composer-layout-collage .composer-media-item,
.composer-media-block.composer-layout-hero .composer-media-item{display:flex;flex-direction:column;min-height:0;overflow:hidden}
.composer-media-block.composer-layout-collage .composer-media-item>a,
.composer-media-block.composer-layout-hero .composer-media-item>a{flex:1 1 auto;height:auto;min-height:0}
.composer-media-block.composer-layout-collage .cm-credit,
.composer-media-block.composer-layout-hero .cm-credit{flex:0 0 auto}

/* ── Editable site pages: About, Terms, Privacy ───────────────────────────── */

/* One typographic treatment for all three, because they now come out of one
   renderer. Before this they were three: About styled every element inline,
   Terms and Privacy leaned on an inline padding and two class names
   (.box-head/.box-body) that no stylesheet has ever defined. Keeping the
   styling here also means what an admin edits in the Pages tab is plain
   readable HTML instead of a wall of style attributes to preserve by hand. */
/* The font goes on the container, not only on the paragraphs, so `ch` is
   measured in the face the prose is actually set in. Left to the inherited
   11px Verdana it produced a measure a third too narrow. */
.page-prose{max-width:70ch;font:13px/1.75 Georgia,'Times New Roman',serif}
.page-prose h1{margin:0 0 6px;font:bold 24px Arial,Helvetica,sans-serif;color:var(--g-text-heading);letter-spacing:-.5px;line-height:1.15}
.page-prose h2{margin:22px 0 8px;font:bold 14px Arial,Helvetica,sans-serif;color:var(--g-text-heading)}
.page-prose h3{margin:20px 0 6px;font:bold 13px Arial,Helvetica,sans-serif;color:var(--g-text-heading)}
.page-prose h2:first-child,.page-prose h3:first-child{margin-top:0}
.page-prose p{margin:0 0 14px}
.page-prose ul{margin:0 0 14px;padding-left:20px;line-height:1.7}
.page-prose li{margin-bottom:6px}
.page-prose hr{border:none;border-top:1px solid var(--g-border-subtle);margin:20px 0}
.page-prose>*:last-child{margin-bottom:0}
.page-prose-updated{margin:0 0 20px!important;color:var(--g-legacy-muted);font:11px Verdana,Arial,sans-serif!important}

/* The box head is a styled bar, and the page's title belongs in it as a real
   heading rather than beside it as a second copy. */
.page-box .hd h1{margin:0;font:inherit;color:inherit;letter-spacing:0}
/* Constrain the card, not just the text inside it: a reading measure floating
   in a full-width box leaves two thirds of the card empty. */
.page-box{max-width:820px}
.page-box .bd{padding:18px 20px}

/* About keeps its two columns; the prose column is the editable half. */
.about-layout{display:flex;gap:24px;align-items:flex-start;padding:6px 0 20px}
.about-main{flex:1;min-width:0}
.about-aside{width:250px;flex:none;min-width:0}
.about-aside .box{margin-bottom:16px}
.about-facts{padding:2px 10px 4px}
.about-fact{display:flex;gap:10px;padding:7px 0;border-bottom:1px solid var(--g-border-subtle);font-size:11px}
.about-fact span{color:var(--g-legacy-muted)}
.about-fact b{margin-left:auto;text-align:right}
.about-fact:last-child{border-bottom:0}
.about-cta-copy{margin:0 0 10px;line-height:1.6}
@media(max-width:760px){.about-layout{flex-direction:column}.about-aside{width:100%}}

/* ── Comments: one row design, in the feed and on the permalink ───────────── */

/* The permalink thread now renders the same row the feed does, so the row
   styling has to reach outside .post, where the feed's copy lives. These are
   the same declarations keyed on .h2-thread rather than on .post .cmts. */
.h2-thread .c.reply-row{display:flex;gap:6px;padding:6px 0;margin:0;border-left:0;border-top:1px dotted var(--g-border-subtle);font-size:11px}
.h2-thread .c.reply-row:first-child{border-top:0}
.h2-thread .c.reply-row.depth1{margin-left:22px;border-left:2px solid var(--pc-subtle-border,var(--g-border-subtle));padding-left:8px}
.h2-thread .c a{font-weight:bold}
.h2-thread .cav{flex:none;width:22px;height:22px;border:1px solid var(--g-border-default,#999);background:var(--pc-header,var(--g-post-headerSurface,#7a8ca3));overflow:hidden;display:block}
.h2-thread .cav img{width:100%;height:100%;object-fit:cover;display:block}
.h2-thread .ctext{flex:1;line-height:1.45;min-width:0;word-wrap:break-word;overflow-wrap:anywhere}
.h2-thread .cstamp{font-size:11px;color:var(--g-post-muted,#6b6b6b);font-weight:normal}

/* Name line, body and actions each get their own line. Run together, the
   actions read as the end of the sentence: "…so the layout has to cope with
   it Reply · ♡". */
.c.reply-row .cmeta,.c.reply-row .cbody{display:block}
.c.reply-row .cbody{margin:1px 0 2px}
.c.reply-row .reply-acts{display:flex;align-items:center;gap:8px;margin-top:1px}

/* The delete control belongs with the other actions rather than floated into
   the timestamp, and needs a hit area, not a bare glyph. */
.reply-acts .del-comment-form{display:inline;margin:0}
.reply-acts .cdel{background:none;border:0;cursor:pointer;color:var(--g-danger,#991f2f);font-size:11px;padding:0 2px;line-height:1}
.reply-acts .cdel:hover{text-decoration:underline}

.h2-thread-empty{font-size:11px;color:var(--g-legacy-muted);padding:6px 0}
/* Under the previews it follows, so it needs to sit left with them rather than
   floating right off the end of a list it is no longer above. */
.cmts a.viewall{display:inline-block;text-align:left;padding-top:5px}

/* Reply and the heart are buttons now, so they need to stop looking like
   buttons: they sit in a line of 10px metadata, not in the action bar. */
.reply-acts .reply-link,.reply-acts .clike-btn{background:none;border:0;padding:1px 2px;margin:0;font:inherit;color:var(--pc-muted,var(--g-post-muted,#6b6b6b));cursor:pointer;line-height:1;min-height:20px}
.reply-acts .reply-link:hover,.reply-acts .clike-btn:hover{color:var(--pc-action-active,var(--g-post-actionActive,#b35900));text-decoration:underline}
.reply-acts .reply-link:focus-visible,.reply-acts .clike-btn:focus-visible{outline:2px solid var(--pc-focus,var(--g-focus-ring,#005fcc));outline-offset:2px}
.reply-acts .clike-btn.liked{color:var(--pc-action-active,var(--g-post-actionActive,#cc0000))}
.reply-acts .clike-btn[disabled]{opacity:.6;cursor:default}

/* Who the comment box is currently aimed at, with a way out of it. */
.add-comment-replying{margin:0 0 5px;font-size:11px;color:var(--g-legacy-muted)}
.add-comment-replying b{color:var(--g-text-heading)}

/* ── Account menu ─────────────────────────────────────────────────────────── */

/* The panel's items were near-white on orange -- 1.66:1, effectively
   unreadable -- and hovering one changed nothing at all.

   Two causes. `#header .search .auth a:not(.btn){color:var(--g-header-text)
   !important}` above exists to keep the header's own links legible on the navy
   bar, and the account menu happens to sit inside .auth, so every item in the
   dropdown inherited header-white on the panel's cream-orange. Being both
   !important and more specific than `.acctmenu-panel a`, it won. And the hover
   surface resolved to --g-nav-activeSurface, which is the same #f5be6c the
   panel itself is painted with, so the "hover state" was the panel background.

   Matching the header rule's specificity fixes the first; a lighter surface
   with the dark nav text fixes the second. 11.2:1 at rest, 8.6:1 on hover. */
#header .search .auth .acctmenu-panel a,
#header .search .auth .acctmenu-panel a:visited{color:var(--g-text-primary,#101114)!important}
#header .search .auth .acctmenu-panel a:hover,
#header .search .auth .acctmenu-panel a:focus-visible{
  background:var(--g-nav-hoverSurface,#ffd9a3);
  color:var(--g-nav-activeText,#52321d)!important;
}
/* The whole row is the target, so the pointer should say so before the colour
   does. */
.acctmenu-panel a{cursor:pointer}

/* ── Page width ───────────────────────────────────────────────────────────── */

/* The shell is centred and fixed-width, so every navigation between a page long
   enough to scroll and one that is not moved the entire site sideways by half a
   scrollbar. Reserving the gutter costs nothing on a page that scrolls and
   holds the layout still on one that does not. Browsers without it behave as
   they do today. */
html{scrollbar-gutter:stable}

/* The mood sat after a bare <br>, which inherited the line box of whatever was
   above it and opened a gap before "is feeling:". Its own block, with the line
   height it actually wants. */
.prof-feeling{display:block;margin-top:1px;line-height:1.45}

/* ── Post card: header rule, and a pagination dot you can pick out ────────── */

/* A band under the identity line. .post .top already carried a
   `border-bottom: 1px solid transparent` -- the slot was there and empty, so
   the avatar, name and location ran straight into the caption with nothing
   separating who posted from what they posted. */
.post .top{border-bottom:3px solid var(--g-legacy-headerBg,#ffcc99)}

/* The active dot was styled identically to the idle ones, everywhere it
   actually appears. post-card-refresh.css sets the idle bullet through a
   selector list whose second member, `.post .gallery .swiper-pagination-bullet`,
   is more specific than the active rule beside it -- so inside a post card,
   which is the only place these carousels are, the idle background and its
   .45 opacity won on the active bullet too. There was no way to tell which
   photo you were on.

   Matched specificity, and differentiated by shape as well as colour so the
   current photo is legible without having to compare two oranges. */
.post .gallery .swiper-pagination-bullet{transition:width var(--g-motion-fast,120ms ease),opacity var(--g-motion-fast,120ms ease)}
.post .gallery .swiper-pagination-bullet-active,
.post .gallery .swiper-pagination-bullet.swiper-pagination-bullet-active{
  width:18px;opacity:1;
  background:var(--g-button-border,#cc7826);
  border-color:var(--g-border-strong,#8a5a33);
}
@media (prefers-reduced-motion: reduce){
  .post .gallery .swiper-pagination-bullet{transition:none}
}

/* ── Art tab ──────────────────────────────────────────────────────────────── */

/* Nothing is cropped, and nothing is left with a hole under it. A grid would
   set every row to the height of its tallest piece, so a portrait next to a
   landscape leaves a gap; columns pack the pieces instead, which is how they
   end up sitting together with one gutter throughout. Column count is fixed
   rather than auto-fit so the rhythm holds whatever mixture of portrait and
   landscape work somebody has. */
.art-grid{columns:3;column-gap:10px;padding:10px 0}
.art-cell{
  display:block;position:relative;padding:0;margin:0 0 10px;width:100%;cursor:pointer;
  break-inside:avoid;-webkit-column-break-inside:avoid;
  background:var(--g-media-tileSurface,var(--g-surface-panel,#fffdf6));
  border:1px solid var(--g-media-tileBorder,var(--g-border-default,#cc7041));
}
/* Reserve the right box before the image lands, so a gallery does not reflow
   itself as it loads. --art-ratio comes from the stored dimensions. */
.art-cell img{display:block;width:100%;height:auto;aspect-ratio:var(--art-ratio,1)}
.art-cell:hover{border-color:var(--g-legacy-accent,#b35900)}
.art-cell:focus-visible{outline:2px solid var(--g-focus-ring,#005fcc);outline-offset:2px}
.art-cell-label{
  display:block;padding:4px 6px;text-align:left;
  font:11px/1.35 Verdana,Arial,sans-serif;
  background:var(--g-media-captionSurface,var(--g-surface-elevated,#fff1ce));
  color:var(--g-media-captionText,var(--g-text-primary,#101114));
}
.art-cell-label b{display:block}
.art-cell-label span{display:block;opacity:.82}
@media(max-width:820px){.art-grid{columns:2}}
@media(max-width:520px){.art-grid{columns:1}}

/* The shadowbox is wider than the report dialog it borrows its chrome from:
   the piece is the point, and .g-dialog's 340px would letterbox it. The width
   goes through --g-dialog-width because dialog.css loads last and its own
   `width` would otherwise win. */
.art-shadowbox{--g-dialog-width:880px;position:relative;padding:16px}
.art-close{
  position:absolute;top:6px;right:8px;z-index:1;padding:2px 7px;line-height:1;
  font-size:18px;cursor:pointer;color:var(--g-text-primary,#101114);
  background:var(--g-button-surface,#f4ead9);border:1px solid var(--g-border-strong,#8a5a33);
}
.art-close:hover{background:var(--g-button-hover,#ffdfbd)}
.art-close:focus-visible{outline:2px solid var(--g-focus-ring,#005fcc);outline-offset:1px}
.art-figure{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(220px,1fr);gap:16px;margin:0}
.art-figure img{display:block;width:100%;height:auto;max-height:70vh;object-fit:contain;background:var(--g-post-mediaMat,#241804)}
.art-record{text-align:left;min-width:0}
.art-record h2{margin:0 0 8px;font:bold 16px Arial,Helvetica,sans-serif;color:var(--g-text-heading)}
.art-record dl{margin:0 0 10px;display:grid;gap:4px}
.art-row{display:grid;grid-template-columns:56px minmax(0,1fr);gap:8px;font-size:11px}
.art-row dt{color:var(--g-legacy-muted,#6b6b6b)}
.art-row dd{margin:0;overflow-wrap:anywhere}
.art-record p{margin:0;font:13px/1.6 Georgia,'Times New Roman',serif}
.art-nav{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:12px;font-size:11px}
.art-nav .pact[disabled]{opacity:.5;cursor:default}
@media(max-width:700px){
  .art-figure{grid-template-columns:1fr}
  .art-figure img{max-height:50vh}
}

/* ── Theme Studio: the six ─────────────────────────────────────────────────── */
.composer-theme-palette .composer-theme-role{padding:9px 0}
.composer-theme-asset-thumb{
  grid-column:1/-1;display:block;max-width:120px;max-height:70px;width:auto;
  border:1px solid var(--g-border-default,#cc7826);background:var(--g-surface-inset,#eef5ff);
}
.composer-theme-token input[type=file]{grid-column:1/-1;font-size:10px;max-width:100%}
.composer-theme-presetbox{border-top:1px solid var(--g-border-subtle,#e8c9a5);padding:8px 0 2px;margin-top:7px}
.composer-theme-presetbox>summary{
  cursor:pointer;font:bold 10px Verdana,Arial,sans-serif;text-transform:uppercase;
  letter-spacing:.04em;color:var(--g-text-heading,#8a3d00);padding:4px 0;
}
.composer-theme-presetbox>summary:focus-visible{outline:2px solid var(--g-focus-ring,#005fcc);outline-offset:2px}

/* A failed save has to stay visible. The status line is polite and transient
   by design, which is right for "Draft saved." and wrong for "nothing you do
   is being stored" -- somebody who misses that message goes on editing and
   concludes the controls are broken. */
.composer-status.bad{
  background:var(--g-danger-bg,#f3e3e3);color:var(--g-danger,#991f2f);
  border:1px solid var(--g-danger,#991f2f);padding:5px 7px;font-weight:bold;
}
.profile-editor-shell.composer-save-failed .composer-inspector{
  box-shadow:inset 0 0 0 2px var(--g-danger,#991f2f);
}
