/*
Theme Name: Wahnsinn August 2026
Theme URI: https://30mom.com/
Description: Website Stuff
Author: LF
Version: 2.0
License: ¯\_(ツ)_/¯
Tags: 30MOM
*/


/* ======================= */
/* Custom Fonts */
/* ------------------------------------------------------------
   Each @font-face block below registers one custom font-family
   name and points it at the actual font files in /assets/fonts/. After
   that, any rule elsewhere in this file — OR an inline style typed
   directly into a post's content via the editor — can use that
   name in a font-family declaration (e.g. font-family: 'MOM',
   monospace;) to apply it. Browsers don't download a font file
   until some actually-rendered text needs it, so an @font-face rule
   that nothing ever uses costs nothing at runtime — it's just dead
   weight in the code, not a performance problem.

   "Usage" below is checked two ways for every font: (1) every
   selector in this stylesheet, and (2) an inline-style scan across
   every published page — a font can be applied directly in post
   content without any theme CSS rule at all (the same trap that
   almost cost .notepaper and .goleft, see their own comments). Two
   fonts ('vcr' and 'Victoria') came up with zero usage by either
   measure and were removed (their woff/woff2 files deleted too); the
   five that remain below are all in genuine use. */
   /* ======================= */

/* 'MOM' Font — the workhorse font. Used 17 times across the file:
   the base body/input/textarea text, the main nav (#navlisttop),
   mobile nav, credits buttons, and several "tape rack" components
   (.vidframe, .perma, .notepaper .quote-by, etc). If you only
   remember one font name in this file, it's this one. */
@font-face {
  font-family: 'MOM';
  src: url('/assets/fonts/moms-typewriter.woff2') format('woff2');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* 'scratch' Font — the "handwritten label" font. Used 12 times:
   some heading levels (h3, h6), and the whole VHS-tape-spine
   family (.vhsl, .vhs, .vhssm, .vhs_sidebar, .vidspine, .30yom) —
   this is the font that actually renders the show-title text
   layered on top of the per-post "vhs" custom-field background
   image on vault/episode listings. */
@font-face {
  font-family: 'scratch';
  src: url('/assets/fonts/scratch.woff2') format('woff2');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'quanta';
  src: url('/assets/fonts/quanta-microgen.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'quanta';
  src: url('/assets/fonts/quanta-microgen-bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* 'traveling' Font — the "blog body copy" font. Used 8 times,
   almost entirely on the .blogtext family (blog/zine post body
   text) plus .caption and one rackmount component. */
@font-face {
  font-family: 'traveling';
  src: url('/assets/fonts/traveling-typewriter.woff2') format('woff2');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* 'Sears' Font — the "blog heading" font. Used 6 times, exclusively
   on .blogtext heading levels (h1, h2, h3, h5, h6) — pairs with
   'traveling' above to give blog/zine posts their own typographic
   identity, separate from the rest of the site. */
@font-face {
  font-family: 'sears';
  src: url('/assets/fonts/sears.woff2') format('woff2');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/****************************
    End Custom Fonts
**********************************************/ 

/* ============================================================
   SITE-WIDE RESET & BASE STYLES
   ------------------------------------------------------------
   These four rules apply to literally every element on every page
   before anything else in this file runs. They're the foundation
   everything else builds on, which also means they're the most
   overridden rules in the whole stylesheet by design — that's not
   redundancy, it's how a CSS reset is supposed to work: zero
   everything out globally, then let each component opt back into
   the specific spacing/sizing/color it actually needs.
   ============================================================ */

/* The universal reset. `* {}` matches every single element on the
   page. Two things happen here:
   1. margin/padding zeroed out everywhere — browsers ship with
      inconsistent built-in spacing on things like <p>, <ul>, <h1>,
      etc.; zeroing it all out means every bit of spacing you see
      anywhere on the site was deliberately added by a rule further
      down the file, not left over from a browser default.
   2. box-sizing: border-box — changes how width/height math works.
      Without this, adding padding or a border to an element makes
      it visually BIGGER than the width you set (padding/border get
      added on top). With border-box, padding and border are
      included inside the width/height you declare instead, so
      "width: 200px" always means 200px on screen, full stop. This
      is why so many rules elsewhere in this file can set a precise
      width/height and padding together without the math going
      wrong — they're all relying on this one line.
   Practically every component rule below this point overrides
   margin/padding/width for its own purposes — that's expected, not
   a conflict with this rule. */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* The page-wide defaults: black background, dark-gray base text
   color, the 'MOM' font (see Custom Fonts above) as the fallback
   typeface for any text that isn't more specifically styled.
   Cross-reference for where this gets overridden: the black
   background here is the "canvas" behind everything — most of the
   site's visible structure (#wrapper, #header, the rack-mount
   components throughout this file) sits on top of it with their
   own background-image PNGs, so you mostly only SEE this black
   body background in the margins/gutters around those components.
   The 'MOM' font fallback gets overridden constantly too — h3/h6
   swap to 'scratch', .blogtext swaps to 'traveling'/'xx', and so
   on (see Custom Fonts above for the full breakdown) — 'MOM' is
   what renders for any plain text that no other rule has claimed. */
body {
  font-family: 'MOM', monospace;
  color: #282828;
  background: #000;
  line-height: 1.5;
  vertical-align: baseline;
}

/* Images — removes the border some very old browsers used to draw
   around <img> elements (especially when wrapped in a link, which
   `a img` handles separately). No current browser does this by
   default, so these two rules are mostly legacy/harmless at this
   point — not actively overridden anywhere because there's nothing
   left to override; just a leftover safety net from an earlier
   browser era. */

img {
  border: 0;
}


a img {
  border: none;
}


/****************************
    Text Elements (Modernized)
    This section looks newer/cleaner than most of the file (rem
    units, grouped comments) — it's a base-level reset/defaults
    layer for plain HTML text elements (h1-h6, a, p, blockquote,
    ul/li) that applies everywhere, before any of the site's
    specific components (rack mounts, tape spines, etc.) add their
    own overrides on top further down the file.
**********************************************/


/* Headings - Consolidated styles
   One shared rule sets defaults for ALL heading levels (no margin,
   bold, all-caps), then each level below overrides just the size/
   spacing it needs to differ. h3 and h6 go further and swap in the
   'scratch' handwritten-label font (see Custom Fonts above) with
   custom color/spacing — those two heading levels are the ones
   actually used as stylized section titles around the site;
   h1/h2/h4/h5 stay plain. */
h1, h2, h3, h4, h5, h6 {
  margin: 0;
  font-weight: normal;
  text-transform: uppercase;
}

h1 {
  font-size: 2rem;
  margin: 0.67em 0;
}

h2 {
  font-size: 1.75rem;
  margin: 0.5em 0;
}

/* line-height:0.6 (tighter than the font's own glyph height) used to
   ship here — invisible for years because every h3 on the site
   happened to fit on one line at the old fixed desktop width, and a
   too-tight line-height only causes visible overlap once a heading
   actually wraps to a second line. Surfaced by the /blog mobile/
   tablet pass: 20-years-of-madness's "Rent the DVD at these fine
   establishments!"/"Get a limited-edition VHS..." headings wrap at
   narrower widths and the second line rendered on top of the first.
   Bumped to 1.1 — unscoped, so this fixes every h3 on the site, not
   just this post, on purpose (confirmed with the owner: h3 is used
   site-wide as this same stylized section-title look, per the
   comment above). */
h3, h3 a {
  font-family: 'scratch', monospace;
  color: #ff3c00;
  font-size: 2.6rem;
  line-height: 1.1;
  letter-spacing: 1.2px;
  margin: 0.4em 0;
}

h4 {
  font-size: 1.3rem;
  margin: 0.67em 0 0;
}

h5 {
  font-size: 1.15rem;
  margin: 0.67em 0;
}

h6, h6 a {
  font-family: 'scratch', monospace;
  font-size: 2.3rem;
  letter-spacing: 0.3px;
  margin: 0.33em 0;
}

/* Links - Consolidated states
   Sets the default look for every link site-wide (orange, no
   underline) plus its visited/hover/active color variants. Any
   component-specific class further down the file that sets its own
   link colors (e.g. .vhsl a:hover) is overriding this baseline
   for that specific component — this is the fallback for plain
   links that don't have a more specific rule. */
a {
  color: #ff3c00;
  text-decoration: none;
  transition: color 0.2s ease; /* Smooth color change */
}

a:visited { color: #cb3102; }
a:hover   { color: #E00000; }
a:active  { color: #ff4e00; }

/* Special link overrides */
h3 a:active { color: #ff7e00; }  /* Only needed override */

/* Paragraphs — default spacing for any plain <p> on the site.
   (Note: inside #content, the margin-bottom here is overridden to
   `auto` by the #content p rule further down — an ID selector
   outranks this bare element rule. The rack-mount components'
   paragraph rhythm lives with the rest of the rack system in the
   =Rack Frame section at the bottom of the file: .rack-content p
   and its per-family overrides.) */
p {
  letter-spacing: 0.2px;
  margin: 0 0 1.5rem;
}

/* (A .rackmountwidetext p rule used to live here — text.php's
   paragraphs now get the identical rhythm from .rack-content p in
   the =Rack Frame section at the bottom of the file.) */

/* Blockquotes — plain <blockquote> default styling. Note this is
   separate from .notepaper (further down the file), which is the
   site's other, much more elaborate blockquote-style component
   used for fan testimonials/quotes — this rule here is just the
   plain, undecorated fallback for any blockquote that isn't
   wrapped in .notepaper. */
blockquote {
  width: 83%;
  max-width: 800px; /* Prevents overly wide quotes on large screens */
  margin: 1.5rem auto; /* Centers the blockquote with vertical spacing */
  padding: 0;
  color: #484848;
}


blockquote p {
  font-size: 1rem; /* 16px → rem */
  line-height: 1.5; /* 24px → unitless for scalability */
  margin: 0 0 1.5rem; /* Bottom margin for paragraphs */
  text-align: left;
}

/* Lists — deliberately strips ALL default list styling (bullets,
   indent, spacing) from every <ul> and <li> on the entire site.
   This matters to understand: most <ul>/<li> elements in this
   theme's templates aren't being used as actual bulleted lists —
   they're used as generic layout/grouping wrappers (nav menus,
   image grids, sidebar items), the same way a lot of older sites
   leaned on <ul><li> for structure before flexbox/grid were common.
   This reset is what makes that possible without bullets showing
   up everywhere; any *real* list that wants bullets back would need
   its own override (none currently do, as far as this audit found). */
ul, li {
  list-style: none;
  padding: 0;
  margin: 0;
}


/****************************
    End Text Elements
**********************************************/

/****************************
    Header
    Three similarly-named header wrapper IDs, each used by a
    different set of templates — easy to mix up by name alone.
**********************************************/

/* #hed — the home-page-style header band (with the big video-header
   GIF). Used by header-home.php and 404.php. */
#hed {
	padding: 0;
	margin-top: 0px;
	height: 461px;
	width: 1100px;
	text-align:center;
}

/* #hedsingle — the shorter header band used on single-item pages.
   Used by header-single.php and artifacto.php. Note it's visually
   much shorter (174px vs #hed's 461px) — this is the "compact"
   header variant for pages that aren't the homepage. */
#hedsingle {
	padding: 0;
	margin-top: 0px;
	height: 174px;
	width: 1100px;
	text-align:center;
}

/****************************
    End Header
**********************************************/

/****************************
    Top Nav Menu
    Used by header.php, 404.php, and artifacto.php — the three
    templates that each hand-roll their own full <head>+nav markup
    instead of sharing one nav partial (404.php and artifacto.php
    don't call get_header()). Worth knowing if this nav ever needs
    a structural change: it has to be edited in three places.

    The .button/.currentbutton (and .epbutton/.currentepbutton) pair
    is a recurring pattern here: header.php picks which class to
    echo per nav item with PHP conditionals like
    `if (in_category('vault')) echo "currentbutton"; else echo "button";`
    — i.e. "current" is the highlighted/active state for whichever
    page you're actually on, "button" is the plain inactive state for
    every other nav item. Note when checking PHP source for class
    usage: search for the bare class name, not a literally-quoted
    attribute string. A search for the literal text `class="button"`
    misses it, since the PHP source writes it as
    `echo " class=\"button\""` — PHP's own string escaping can
    disguise it.
**********************************************/

/* Normal flow, not position:absolute (same change applies to #leftmenu
   and #main below — see the =Main Content Area section's #main rule
   for the full explanation of what this replaced: a chain of
   hand-tuned margin-top:61px values scattered across four different
   selectors, all silently depending on this element's height).
   Letting #topmenu sit in real document flow means it pushes whatever
   comes after it down by its own actual height, automatically — the
   same thing #mobiletopmenu already relied on via its own
   position:static !important override below 1024px width. */
#topmenu {
	background-image: url(/assets/images/structure/topmenu.png);
	background-repeat: no-repeat;
	height:61px;
	width:1100px;
}

#navlisttop{
	height:50px;
	width:1100px;
	margin-left:6px;
}

/* The actual nav links — Main/Vault/Episodes/etc. Uses the 'MOM'
   font (see Custom Fonts at the top of this file). */
#navlisttop li, #navlisttop li a{
	height:50px;
	list-style:none;
	top:0;
	font-family:  'MOM', monospace;
	font-size:16px;
	text-transform:uppercase;
	letter-spacing:1px;
	text-decoration: none;
	line-height: 50px;
	display: block;
	color: #282828;
	text-align:center;
}

#navlisttop li a:hover, #navlisttop li a:active{
	color: #383838;
}

#navlisttop li img {
	padding-top:22px;
	width: 85px;
}

/* .creditsbutton — only used in main.php (the homepage), not part of
   the repeated nav pattern above. A single dedicated button (own
   sprite image, own size) rather than one of the generic nav items. */
.creditsbutton{
	width:119px;
	height: 41px;
	padding:1px 0px 0px 294px;
	display: block;
	top:0;
	font-family: 'MOM', monospace;
	font-size:13px;
	text-transform:uppercase;
	letter-spacing:1px;
	line-height: 39px;
	color: #282828;
	text-align:center;
}

/* Sprite-sheet button technique: creditsbutton.png contains all
   three visual states side by side (normal, hover, active) in one
   image, and each state just shifts the visible window sideways
   with background-position (0, -117px, -234px) instead of swapping
   to a different image file — one fewer image request, and no flash
   of a blank image while a second file loads on hover. A subtle
   static green box-shadow (matching creditsbutton.png's own green)
   is repeated in all three state rules below so the glow never
   flickers off between states — replaces the old pulsing
   text-shadow animation (former "glowell" keyframes).
   "facebreathe" (search "@keyframes facebreathe") is a slow
   brightness pulse so the button face itself (and
   its box-shadow halo, since `filter` composites the whole element)
   reads as gently humming/glowing rather than flat and static. */
.creditsbutton a:link, .creditsbutton a:visited{
	background:url('/assets/images/structure/creditsbutton.png') 0 0;
	font-family: 'MOM', monospace;
	height: 41px;
	width:119px;
	left:0px;
	display: block;
	text-decoration: none;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.creditsbutton a:hover{
	background: url('/assets/images/structure/creditsbutton.png') -117px 0;
	font-family: 'MOM', monospace;
	height: 41px;
	width:119px;
	display: block;
	color: #383838;
	animation: facebreathe 3.15s ease-in-out infinite;
}

 .creditsbutton a:active{
	background: url('/assets/images/structure/creditsbutton.png') -234px 0;
	font-family: 'MOM', monospace;
	height: 40px;
	width:119px;
	display: block;
	color: #383838;
	animation: facebreathe 3.15s ease-in-out infinite;
}

/* .currentbutton — the "you are here" highlighted state for a main
   nav item (see the PHP-conditional explanation in the section
   banner above). Same sprite-sheet technique as .creditsbutton:
   button.png holds normal/hover/active side by side, this rule
   starts at the "current page" frame (-200px) since it's always
   shown as already-active, then shifts to the hover frame on
   hover/active interaction. */
.currentbutton{
	width:100px;
	margin-left:8px;
	background: url('/assets/images/structure/button.png') -200px 0;
	display: block;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float:left;
}

.currentbutton a:hover, .currentbutton a:active{
	background: url('/assets/images/structure/button.png') -100px 0;
	animation: facebreathe 3.15s ease-in-out infinite;
}

/* .button — the plain/inactive state of a main nav item (the "else"
   branch of the same PHP conditional that picks .currentbutton for
   whichever page is actually active). Starts at the sprite's first
   frame (0,0) since there's no "current" highlight to show. A static
   yellow box-shadow (matching button.png's own color) sits on the
   container so it holds steady across hover/current state changes,
   instead of the old pulsing text-shadow animation (former "glowell"
   keyframes, now removed). */
.button{
	background-repeat: no-repeat;
	height:50px;
	width:100px;
	margin-left:8px;
	background:url('/assets/images/structure/button.png') 0 0;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float: left;
}

.button a:hover, .button a:active{
	background: url('/assets/images/structure/button.png') -100px 0;
	background-repeat: no-repeat;
	animation: facebreathe 3.15s ease-in-out infinite;
}

/* .currentepbutton / .epbutton below are the exact same pattern as
   .currentbutton / .button above, just for the "Episodes" nav item
   specifically — it gets its own sprite (epbutton.png) and its own
   pair of classes rather than reusing .button/.currentbutton. Not
   an accident or duplication to "fix"; it's how header.php's
   conditional picks between them for that one nav item. Box-shadow
   color matches epbutton.png's red rather than the yellow used above. */
.currentepbutton{
	width:100px;
	margin-left:8px;
	background: url('/assets/images/structure/epbutton.png') -100px 0;
	display: block;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float:left;
}

.currentepbutton a:hover, .currentepbutton a:active{
	background: url('/assets/images/structure/epbutton.png') -100px 0;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.epbutton{
	background-repeat: no-repeat;
	height:50px;
	width:100px;
	margin-left:8px;
	background:url('/assets/images/structure/epbutton.png') 0 0;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float: left;
}

.epbutton a:hover, .epbutton a:active{
	background: url('/assets/images/structure/epbutton.png') -100px 0;
	background-repeat: no-repeat;
	animation: facebreathe 3.15s ease-in-out infinite;
}


/****************************
    End Top Nav Menu
**********************************************/

/****************************
    Mobile Top Nav Menu
    This section only defines what the mobile nav LOOKS like (sized,
    positioned, sprite-button styling) — it does NOT control when
    it's actually visible. That's a separate, real, intentional split:
    a rule far down this file (search "#mobiletopmenu" again, inside
    "@media screen and (max-width: 1024px)") hides the desktop
    #topmenu and shows this #mobiletopmenu once the screen narrows
    past 1024px. So #mobiletopmenu appears twice in this file on
    purpose — once here for appearance, once there for visibility —
    not an accidental duplicate. Used by header.php only.
**********************************************/


/* Normal flow, not position:absolute (see the matching note on
   #topmenu above). This was already effectively
   static whenever actually visible, via the position:static !important
   override below 1024px width (search "#mobiletopmenu" further down,
   inside the visibility-swap section) — that override is now
   redundant and has been removed too, since static is the default. */
#mobiletopmenu {
	background-image: url(/assets/images/structure/mobiletopmenu.png);
	background-repeat: no-repeat;
	height:210px;
	width:1100px;
}

/* Same idea as #navlisttop in the desktop nav above, just bigger
   (mobile-friendly tap targets: 32px text vs 16px, 170px icons vs
   85px). */
#mobilenavlisttop{
	height:100px;
	width:1100px;
	margin-left:-6px;
}

#mobilenavlisttop li, #mobilenavlisttop li a{
	height:100px;
	list-style:none;
	top:0;
	font-family:  'MOM', monospace;
	font-size:32px;
	text-transform:uppercase;
	letter-spacing:1px;
	text-decoration: none;
	line-height:100px;
	display: block;
	color: #282828;
	text-align:center;
}

#mobilenavlisttop li a:hover, #mobilenavlisttop li a:active{
	color: #383838;
}

#mobilenavlisttop li img {
	padding-top:22px;
	width: 170px;
}

/* .mobilebutton / .currentmobilebutton — the exact same
   plain/"current page" pattern as .button/.currentbutton in the
   desktop nav above (same PHP-conditional technique in header.php,
   confirmed directly: `echo "currentmobilebutton"` vs
   `echo "mobilebutton"` per nav item), just using mobilebutton.png
   as its own 3-frame sprite sheet instead of button.png. */
.mobilebutton{
	background-repeat: no-repeat;
	height:100px;
	width:200px;
	margin-left:19px;
	background:url('/assets/images/structure/mobilebutton.png') 0 0;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float: left;
}

.mobilebutton a:hover, .mobilebutton a:active{
	background: url('/assets/images/structure/mobilebutton.png') -200px 0;
	background-repeat: no-repeat;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.currentmobilebutton{
	width:200px;
	margin-left:19px;
	background: url('/assets/images/structure/mobilebutton.png') -400px 0;
	display: block;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float:left;
}

.currentmobilebutton a:hover, .currentmobilebutton a:active{
	background: url('/assets/images/structure/mobilebutton.png') -200px 0;
	animation: facebreathe 3.15s ease-in-out infinite;
}

/* .epmobilebutton / .currentepmobilebutton — the mobile Episodes
   button. Desktop has its own red epbutton.png sprite (see .epbutton
   above); mobile reuses that exact same image rather than shipping a
   second one, just scaled 2x via background-size (300x50 -> 600x100)
   to match mobilebutton.png's native 200x100-per-frame size. The
   background-position values are epbutton's desktop offsets (0,
   -100px) doubled to match. */
.epmobilebutton{
	background-repeat: no-repeat;
	height:100px;
	width:200px;
	margin-left:19px;
	background: url('/assets/images/structure/epbutton.png') 0 0;
	background-size: 600px 100px;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float: left;
}

.epmobilebutton a:hover, .epmobilebutton a:active{
	background: url('/assets/images/structure/epbutton.png') -200px 0;
	background-size: 600px 100px;
	background-repeat: no-repeat;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.currentepmobilebutton{
	width:200px;
	margin-left:19px;
	background: url('/assets/images/structure/epbutton.png') -200px 0;
	background-size: 600px 100px;
	display: block;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
	float:left;
}

.currentepmobilebutton a:hover, .currentepmobilebutton a:active{
	background: url('/assets/images/structure/epbutton.png') -200px 0;
	background-size: 600px 100px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

/****************************
    End Mobile Top Nav Menu
**********************************************/


/****************************
    Infinite M & IMC
**********************************************/

/* Same stale #topmenu-clearance hack as everywhere else in this file
   (see #topmenu/#leftmenu/#main above) has been removed — no longer
   needed now that #topmenu is real document flow. Used on main-im.php
   (the /im sandbox) as a plain block sitting BEFORE .main-columns (the
   #leftmenu/#container flex row) — a flex-basis:100% + #main
   flex-wrap:wrap approach was tried and reverted (see .main-columns
   below for why); as a plain block this just stacks above
   .main-columns via ordinary document flow, no flex participation
   needed at all. */
.flex-im {
	background-image: url(/assets/images/structure/blanktray.gif);
    background-repeat: no-repeat;
    background-size: 100% 100%; /* Stretches width and height to 100% */
	margin-left: 13px;
	width: 1071px;
	height: 555px;
	display: flex; /* Forces child elements to sit side-by-side */
	gap: 10px;     /* Optional: Adds space between the two divs */
}

#infinite-m {
	height: 480px;
	width: 640px;
}

#imc {
	height: 480px;
	width: 421px;
}

/****************************
    End Infinite M & IMC
**********************************************/


/****************************
    Rack / VCR Display Components
    Used by main.php, loop-customcat.php, and catsingle.php to lay
    out episodes and vault entries inside the "VCR rack" visual
    (video trays, rack-mount frames, wide/blog/zine variants).
**********************************************/ 

/* I THINK IT MAY NOT BE USED ANYMORE .rackvidtray — used once, in main.php, wrapping the homepage's
   promo-trailer <video> embed (the archive.org-hosted video flagged
   in the static-flattening to-do — this is its CSS frame).
   margin:0 cancels the browser's default <figure> margin (1em 40px)
   so nothing shifts. */
.rackvidtray {
	margin: 0;
	height: 533px;
	width: 711px;
   	text-align: center;
}

.rackvidtray img {
        width: 711px;
}

.rackvidtray:hover img {
	opacity:.93;
}

.rackvidtray:active img {
	opacity:1.0;
}

/* .mainpromo — the homepage's bare <video>, no longer wrapped in
   .rackvidtray (see the comment above). Left at the browser's
   default display:inline, it's treated as an inline replaced element
   and reserves line-box space below its own baseline for text
   descenders, leaving a ~9px gap before the next sibling — the same
   inline-image line-box gap documented elsewhere in this file (see
   .rackmountplacer img). display:block removes it. */
.mainpromo {
	display: block;
}

/*************************************************************** 

30MOM "locura" video tag player (primarily for use in vault, episodes)

**********************************************/ 

.locura-video-player {
    position: relative;
	width: 640px;
	max-width: 100%;
    aspect-ratio: 4 / 3;
	margin: 0 auto;
    overflow: hidden;
}

.locura-video-player__video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.locura-video-player__tag {
    position: absolute;
    inset: 0;

    display: block;
    width: 100%;
    height: 100%;
    object-fit: fill;

    opacity: 1;
    pointer-events: none;
    z-index: 10;
}

/*
 * Only opening tags are faded and removed.
 * Ending tags remain on their final transparent frame.
 */
.locura-video-player__tag--opening {
    transition: opacity 0.7s linear;
}

/*
 * End-of-video poster and replay layer
 */

.locura-video-player__end-poster {
    position: absolute;
    inset: 0;
    z-index: 20;

    display: block;
    width: 100%;
    height: 100%;

    padding: 0;
    border: 0;
    margin: 0;

    cursor: pointer;
    overflow: hidden;
    background: #000;

    opacity: 0;
    transition: opacity 1s ease;
}

.locura-video-player__end-poster.is-visible {
    opacity: .75;
}

.locura-video-player__end-poster-image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/*
 * Centered replay PNG over the poster.
 */

.locura-video-player__replay-symbol {
    position: absolute;
    top: 50%;
    left: 50%;

    transform: translate(-50%, -50%);

    width: 77px;
    height: 76px;

    background-image: url("/assets/images/tags/replay-icon.png");
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;

    border: 0;
    border-radius: 0;

    color: transparent;
    font-size: 0;
    line-height: 0;
}

/*
 * End locura video tag elements.
 */


/* .albums — used in sidebar-custom.php for the photo-gallery links
   (1990s Photos, Flyers, Artwork, Gifs, etc. — the row of sidebar
   thumbnail links on the homepage). */
.albums {
   	text-align: center;
	padding: 0px;
}

.albums img {
	opacity:1;
	/* Images are inline by default and pick up the browser's normal
	   baseline alignment, which leaves a small gap below each one —
	   block kills that so the stacked album spines sit flush, same
	   fix .rack-content--img img uses for the same reason. */
	display: block;
}

.albums:hover img {
	opacity:.93;
}

.albums:active img {
	opacity:1.0;
}

/* #topper/#botter (standard-width rack end-caps) replaced by
   .rack-cap--narrow (see =Rack Frame). The wider
   variant (#topperwide/#botterwide/.fullwrapwide/.blogwrapwide,
   which used to live here) was replaced by .rack-cap--wide/
   .rack-paper--wide — see =Rack Frame at the bottom
   of this file for the whole system. */

/* .picswrapwide — used only in pics.php (the Gallery template). */
.picswrapwide {
	width: 1100px;
	height: 690px;
	margin: 0px 0px -12px 12px;
	text-align:center;
}

/* .artifactowrap — used only in artifacto.php (the Flash-emulator
   page). Plain black background, no rack-mount image — this page's
   visual is the embedded Ruffle/Flash player, not the rack imagery
   used by the rest of these wrap classes. */
.artifactowrap {
	background-color: #000000;
	width: 1074px;
	height: 920px;
	margin: 0px 0px -12px 12px;
	text-align:center;
}

/* The player <iframe> (post content, artifacto.php) has no
   frameborder/border attributes of its own, so two browser UA
   defaults were showing against the black void behind it: a 2px
   inset border, and the few px of baseline whitespace every inline
   replaced element (iframe's default display) leaves below itself.
   Neither is related to Ruffle — reset here so the player sits flush
   and seamless. */
.artifactowrap iframe {
	display: block;
	border: 0;
}

/* .fullwrap — replaced by .rack-paper--narrow (see =Rack Frame).
   The loop-customcat.php "xzines" branch's
   `id="fullwrap"` doesn't count as a reference — that branch is
   unreachable dead code (no "xzines" category exists). */

/* #vidbox — replaced by .rack-screen (see =Rack Frame). */


/* .musicshelf — used in loop-customcat.php's "music" category
   branch (the /music archive listing). */
.musicshelf {
	margin: 0px 0px 0px 13px;
	width: 1074px;
}

.musicplayer {
	background-image: url(/assets/images/structure/imradio-rack.png);
	background-repeat: no-repeat;
	margin: 0px 0px 0px 3px;
	width: 1094px;
	height: 270px;
}

/* .rackmountcredits — replaced by .rack-content/.rack-content--credits
   (see =Rack Frame). */

/* .rackmountzines — replaced by .rack-content/.rack-content--zines
   (see =Rack Frame). */

/* .rackmountplacer — used in loop-customcat.php, specifically for
   the music-category thumbnail (the .musicshelf branch a bit above
   this) and also the now-confirmed-dead xzines branch. Stays active
   thanks to the live music-category usage. */
.rackmountplacer {
	text-align:center;
	width:1074px;
}

.rackmountplacer img {
	width:537px;
	height: auto;
	float: left;
}

/* .blurb — used directly in post content, not any template:
   confirmed on /blog/20-years-of-madness, /updates, and the
   /20yearsofmadness redirect target. Same "pasted into specific
   posts" pattern as .then/.now/.credits, just spread across a
   handful of related pages instead of just one. */
.blurb {
	font-size: 1.2em;
	line-height: 1.4em;
	width: 90%;
	margin: 0 auto;
	padding: 1em;
	text-align:left;
}


/* .albumgallery — used in loop-page.php (catsingle.php also used
   it before its 2026 rack-frame conversion). */
.albumgallery {
	text-align:center;
	margin-left: 5px;
}

/* WordPress auto-wraps this page's content in a <p>, which otherwise
   picks up the sitewide p { margin: 0 0 1.5rem; } rule and leaves a
   large gap below the last album spine — zeroed here the same way
   .rack-content--img p does for the same reason. */
.albumgallery p {
	margin: 0;
}

/* The album spines are separated by literal <br> tags in the page's
   own content (WordPress wraps them all in one <p>). Now that
   .albums img is display:block, each image already starts its own
   line on its own — the <br> tags are redundant, but don't just
   disappear: left alone, each one still renders as its own empty
   line between the images. Hidden here rather than removed from the
   page content itself, since this is a rendering fix, not a content
   edit. */
.albumgallery br {
	display: none;
}

/* Even with the images genuinely flush (no layout gap at all), a
   visible seam still showed between each one — traced to each spine
   PNG (photos.png, flyers-1.png, artwork-1.png, gifs-lg.png,
   20yom-pics.png) having its own soft, partially-transparent fade at
   its top/bottom edge, not a hard opaque border. Two faded edges
   sitting exactly flush both read as faint right at the seam,
   letting the black page background show through as a band. Pulling
   each image up to overlap the opaque part of the one above hides
   the fade; the exact px values below were measured per image pair
   (each spine's own fade depth, read from its real alpha channel),
   not guessed — if any of these five images are ever replaced, these
   numbers may need re-measuring against the new file. */
.albumgallery .albums:nth-of-type(2) img {
	margin-top: -12px;
}
.albumgallery .albums:nth-of-type(3) img {
	margin-top: -17px;
}
.albumgallery .albums:nth-of-type(4) img {
	margin-top: -10px;
}
.albumgallery .albums:nth-of-type(5) img {
	margin-top: -9px;
}

/* The first and last images have the same soft faded edge as the
   others, but there's no neighboring image to overlap it into at the
   very top/bottom of the whole stack. Two things have to happen
   together: the margin shift moves each image's own already-opaque
   content up/down to sit right at the rack's edge (same idea as the
   overlap trick above, just with nothing to overlap onto), and
   clip-path then hides the strip that shift pushes out past the
   image's own box — clip-path alone wouldn't be enough, since
   clipping without also shifting just turns a soft fade into an
   equally-sized hard-edged gap instead of removing it. Deliberately
   not handled via overflow:hidden on .albumgallery itself — these
   images can end up wider than their container depending on layout,
   and a container-level overflow:hidden would clip that horizontal
   bleed too; clip-path scoped to just these two images avoids that
   entirely regardless of container width. */
.albumgallery .albums:nth-of-type(1) img {
	margin-top: -7px;
	clip-path: inset(7px 0 0 0);
}
.albumgallery .albums:nth-of-type(5) img {
	margin-bottom: -6px;
	clip-path: inset(0 0 6px 0);
}


/* .rackmountwidetext — used only in text.php. */
/* (.rackmountwidetext and .rackmountwideimg used to live here —
   replaced by .rack-content--text and .rack-content--img
   in the =Rack Frame section at the bottom of the file. The old
   `img { text-align: center }` declarations they carried were
   no-ops — text-align does nothing on an img itself — and were
   dropped rather than carried over.) */

/* .picswideimg — used only in pics.php (the Gallery template). */
.picswideimg {
	text-align: center;
	width: 1080px;
	height: 575px;
}

.picswideimg img {
	text-align: center;
	width: 1080px;
	margin-bottom:-20px;
}


/* (.rackmountwideblog used to live here — replaced by
   .rack-content--blog in the =Rack Frame section at the bottom of
   the file, 'traveling' font rhythm and all. Its old
   `padding-bottom: 32px !important` didn't actually need the
   !important — nothing else sets padding on those paragraphs — so
   the new rule drops it.) */

/* .rackmountmerch — used in loop-customcat.php's "merch" category
   branch (the /merch archive listing). margin:0 cancels the
   browser's default <figure> margin (1em 40px) so nothing shifts. */
.rackmountmerch {
	margin: 0;
	text-align: left;
	padding: 0px 0px 0px 12.5px;
}

/* This is an example of the OTHER kind of duplicate in this file —
   not the intentional #mobiletopmenu-style split, just the same
   rule pasted twice in a row with identical properties. The second
   copy below does nothing; everything is already set by the first
   one. Safe to remove in a future cleanup pass. */
.rackmountmerch img{
	width: 538px;
	height: auto;
	float: left;
}

.rackmountmerch img{
	width: 538px;
	height: auto;
	float: left;
}

.rackmountmerch:hover img {
	opacity:.96;
}

.rackmountmerch:active img {
	opacity:.98;
}


/****************************
    Left Sidebar Menu
    This is the shared visual layer for the site's various sidebar
    partials — eps.php, 404.php, sidebar-custom.php,
    sidebar-episodes.php, sidebar-vault.php. Only one of those is
    ever included on a given page (WordPress picks the right sidebar
    per page type), so even though #leftmenu/.sidebarmiddle/
    .sidebarbottom show up in five different template files, they're
    never rendered together — these rules just need to look right
    no matter which sidebar partial happens to be using them.

    Like #mobiletopmenu earlier, #leftmenu also has a second,
    intentional definition further down this file: search
    "#leftmenu" again inside the same mobile @media block — it
    zeroes out the margin-top set here once the mobile nav takes
    over (that margin exists to clear the desktop nav's height,
    which no longer applies on mobile). Same "split on purpose"
    pattern, not a duplicate to merge.
**********************************************/

/* Normal flow, not position:absolute + a hand-tuned margin-top
   (see #main below, which now lays #leftmenu and
   #container side by side with display:flex instead). flex-shrink:0
   keeps this column at its true 350.2px width no matter how wide its
   flex sibling's content gets. */
#leftmenu {
	width:350.2px;
	margin-left:13px;
	flex-shrink: 0;
	text-align:center;
}

#leftmenu ul li {
	padding: 0;

}

#leftmenu li img {
        width: 344px;
}


/* .sidebarmiddle / .sidebarbottom — the repeating background-image
   strips that make up the rest of the sidebar's visual frame
   (middle section repeats vertically to fit any amount of sidebar
   content, bottom caps it off). Used by the same five templates as
   #leftmenu above. */
.sidebarmiddle {
	background-image: url(/assets/images/structure/sidebarmiddle.png);
	background-repeat: repeat-y;
	height: auto;
}

/* li a:hover, not li:hover a — deliberate: with the selector
   triggering off the <li>'s own hover state, any <li> holding more
   than one link (e.g. .sidebargif and .sidebarflyer, each now one
   image) would dim ALL of its links together whenever the mouse was
   anywhere over that <li>, not just the one actually being pointed
   at. Scoping :hover to the anchor itself instead means each link
   dims independently, and is identical in effect everywhere else in
   this sidebar where each <li> only ever held one link. */
.sidebarmiddle li a:hover {
	opacity:.93;
}

.sidebarbottom {
	background-image: url(/assets/images/structure/sidebarbottom.png);
	background-repeat: no-repeat;
	height: 39px;
}


/* .vaultcounter / .vaultbutton below — used only in
   sidebar-custom.php (the homepage's sidebar), not the other four
   sidebar templates. This is the "Vault counter" button/link block
   specifically, a one-off component within the shared sidebar
   frame above, not part of every sidebar. */
.vaultcounter {
	background-image: url(/assets/images/structure/vault-counter.jpg);
	background-repeat: no-repeat;
	height: 86px;
	width: 350px;
	padding-bottom: 10px;
	display: block;
	text-align:center;
	float: left;
}

.vaultbutton {
	width: 63px;
	height: 29px;
	padding: 43px 0px 0px 243px;
	display: block;
	top:0;
	font-family: 'MOM', monospace;
	font-size: 12px;
	text-transform:uppercase;
	letter-spacing: 2px;
	line-height: 30px;
	text-align:center;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.vaultbutton a:link, .vaultbutton a:visited{
	background:url('/assets/images/structure/vault-button.png') -63px 0;
	font-family: 'MOM', monospace;
	height: 29px;
	width: 63px;
	left:0px;
	display: block;
	text-decoration: none;
	color: #282828;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.vaultbutton a:hover{
	background: url('/assets/images/structure/vault-button.png') 0 0;
	font-family: 'MOM', monospace;
	height: 29px;
	width: 63px;
	display: block;
	color: red;
	animation: facebreathe 3.15s ease-in-out infinite;
}

 .vaultbutton a:active{
	background: url('/assets/images/structure/vault-button.png') 63px 0;
	font-family: 'MOM', monospace;
	height: 29px;
	width: 63px;
	letter-spacing: 1px;
	font-size: 11px;
	display: block;
	color: #383838;
	 animation: facebreathe 3.15s ease-in-out infinite;
}

/* .streamingbuttons — used only in sidebar-custom.php (homepage
   sidebar) — the row of streaming-service logos (Apple TV, Amazon,
   etc). .widestreamingbuttons below is its wider sibling, used
   directly in post content instead (see its own comment). */
.streamingbuttons {
	width: 344px;
	margin-left:3px;
}

.streamingbuttons img {
     width: 114.6px;
	 transition: transform .2s; /* Animation */
	animation: facebreathe 3.15s ease-in-out infinite;
}

.streamingbuttons a:hover img {
	opacity:.93;
	transform: scale(1.01); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
	animation: facebreathe 3.15s ease-in-out infinite;
}

.streamingbuttons a:active img {
  transform: scale(.97); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
  animation: facebreathe 3.15s ease-in-out infinite;
}

/* Used directly in post content, not applied by any template — the
   wide variant of .streamingbuttons (see above) for posts with a
   row of streaming-service buttons (Apple TV/Amazon/Tubi/etc). */
.widestreamingbuttons {
	width: 1000px;
	margin-left:3px;
}

.widestreamingbuttons img {
     width: 175px;
	 transition: transform .2s; /* Animation */
     animation: facebreathe 3.15s ease-in-out infinite;
}

.widestreamingbuttons a:hover img {
	opacity:.93;
	transform: scale(1.01); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
	animation: facebreathe 3.15s ease-in-out infinite;
}

.widestreamingbuttons a:active img {
  transform: scale(.97); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
}
/* .sidetray / .artibtn below — used only in sidebar-custom.php
   (homepage sidebar): the "Artifacto" link button at the bottom of
   the sidebar, .sidetray being its background tray and .artibtn the
   clickable button on top of it. */
.sidetray {
	background-image: url(/assets/images/structure/sidetray.png);
	background-repeat: no-repeat;
	height: 78px;
	width: 350px;
	padding-bottom: 0px;
	display: block;
	text-align:center;
}

.artibtn {
	height: 74px;
    width: 70px;
	padding: 2px 0px 0px 140px;
	display: block;
	text-align:center;
	animation: facebreathe 3s ease-in-out infinite;
}

.artibtn a:link, .artibtn a:visited {
	background:url('/assets/images/structure/artibtn.png') -70px 0;
	height: 74px;
	width: 70px;
	display: block;
	animation: facebreathe 3s ease-in-out infinite;
}

.artibtn a:hover {
	background: url('/assets/images/structure/artibtn.png') 70px 0;
	height: 74px;
	width: 70px;
	display: block;
	animation: facebreathe 3s ease-in-out infinite;
}

.artibtn a:active {
	background: url('/assets/images/structure/artibtn.png') 0px 0;
	height: 74px;
	width: 70px;
	animation: facebreathe 3s ease-in-out infinite;
}

/****************************
    End Left Sidebar Menu
**********************************************/ 

/****************************
    update glow text elements
    This section is two things bundled together: the ".updated"
    component (the sidebar "Updates" link/button — see sidebar-
    custom.php), and four @keyframes animations that get reused by
    name from all over this file, not just by .updated.
**********************************************/

/* .updated — the "Updates" link in the homepage sidebar
   (sidebar-custom.php: `<div class="updated"><a href="...">...`).
   Uses the 30MOMRegular font via the `font:` SHORTHAND property —
   see the note on '30MOMRegular' in Custom Fonts at the top of this
   file for the story of how an earlier search missed this usage by
   only checking for `font-family:` and not the shorthand form. */

.updated {
	font-family: 'quanta', monospace;
	color: #ff3c00;
	font-size: 16px;
	font-weight: 700;
	letter-spacing: .7px;
	text-transform:uppercase;
	text-shadow: 1px 1px 3px #ff3c00, -1px -1px -3px #ff3c00;
	animation: glower 1.7s infinite;
	text-align: center;
}

.updated a:link {
  color: #ff3c00;
  text-decoration: none;
}

.updated a:visited {
  color: #ff3c00;
  text-decoration: none;
}

.updated a:hover {
  color: #ff3c00;
  text-decoration: none;
}

.updated a:active {
  color: #ff3c00;
  text-decoration: none;
}

/* Pulsing text-glow animations, named/colored separately so
   different components can each have their own glow color. Like
   @font-face, an unused @keyframes definition costs nothing at
   runtime (browsers don't do anything with it until something
   actually references it by name in an `animation:` property) —
   it's dead weight in the code, not a performance issue.

     - glower  — used by .updated above (red glow). */

@keyframes glower {
  from { text-shadow: 0 0 9px red; }
  50% { text-shadow: 0 0 7px #cc3300; }
  to { text-shadow: 0 0 9px red; }
}

/* "facebreathe" — a slow brightness pulse (not a color/text-shadow
   effect like the ones above) used for every nav button
   (.creditsbutton, .button/.currentbutton, .epbutton/.currentepbutton,
   .mobilebutton/.currentmobilebutton, .epmobilebutton/
   .currentepmobilebutton). `filter: brightness()` composites the
   whole element as rendered — background sprite AND the box-shadow
   halo together — so the button face and its outer glow brighten and
   dim as one unit, reading as a gently humming light rather than a
   static rectangle with a static halo around it. One shared keyframe
   works for all three button colors (yellow/red/green) since
   brightness is a multiplier, not a hue. */
@keyframes facebreathe {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.15); }
}

/****************************
    end update glow text elements
**********************************************/

/* Make the element rotate infinitely. */
/* This comment block (and the vendor-prefixed -ms-/-moz-/-webkit-/
   -o-transform lines below) reads like a generic snippet pasted in
   from somewhere else, not custom-written for this site — those
   vendor prefixes were needed for CSS transforms/animations around
   2010-2012; no current browser needs any of them anymore, they're
   just harmless leftovers alongside the modern unprefixed
   `transform`/`@keyframes` that actually do the work today. */
/*
Usage
    .myElement {
        animation: rotating 3s linear infinite;
    }
*/
@keyframes rotating {
  from {
    -ms-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -webkit-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -ms-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

/* .rotating-css — despite the "Usage" example above describing an
   infinite 3s spin, this is actually applied as a quick 5-spin
   burst (0.1s × 5 iterations), not infinite rotation — the comment
   above is generic/borrowed documentation, not a description of
   how this specific class behaves. Used directly in post content,
   not any template: confirmed only on /contact, wrapping a spinning
   smiley-face image next to the email address. Single-post usage,
   same pattern as .then/.now/.credits/.blurb earlier in this file. */
.rotating-css {
    animation: rotating .1s linear;
    animation-iteration-count: 5;
}

/****************************
    End Rotate
**********************************************/

/****************************
    Tape-Spine & Thumbnail Components
    The .vhs/.vhssm/.vhs_sidebar/.vidspine family renders the
    VHS-spine-style links seen on the homepage and vault/episode
    sidebars; the per-post artwork comes from the "vhs" custom
    field (see main.php, sidebar-vault.php), not a fixed image set.
    .preview/.sidebargif/.boxpreview/.gifpreview are thumbnail
    frames used across the gallery/gifs/flyers listing templates.
**********************************************/ 

/* .preview — used in main.php (homepage) and loop-customcat.php's
   vault/merch category branches: the square video-thumbnail card
   wrapper around the_post_thumbnail() output. */
.preview {
	background:#000000;
	height:263px;
	width:350.2px;
}

.preview img {
	height:100%;
	width:100%;
}

.preview:hover img {
	opacity:.93;
}

.preview:active img {
	opacity:1.0;
}

/* .sidebargif — used in 404.php and sidebar-custom.php (homepage
   sidebar). height:auto (rather than a fixed 258px, a single 640x480
   gif's natural size at this box's 344px width) lets the box grow to
   fit whatever image renders — a leftover from when this box briefly
   held two stacked images at once, kept since it's harmless for a
   single image and one less thing to revert if a second image ever
   ends up here again. wahnsinn_render_daily_pick_image() (functions.php
   section 19) now renders exactly one image per box. Also harmless on
   404.php's single static image, since that gif's own 640x480 ratio
   already matches 344x258 exactly. */
.sidebargif {
	height:auto;
	width:344px;
	margin-left: 3.4px;
}

.sidebargif img {
	height:100%;
	width:100%;
}

/* #leftmenu #widget-area p — now dead for the homepage sidebar
   specifically: wahnsinn_render_daily_pick_image() replaced both
   "Recent Posts Widget Extended" instances with plain PHP output (no
   #widget-area, no <p> wrapper at all), so neither .sidebargif nor
   .sidebarflyer can ever match this selector anymore. Left in place
   since sidebar.php still reuses the bare #widget-area id for its own
   (currently inactive) sidebar-2 widget area — this rule may still
   matter there if that's ever reactivated. */
#leftmenu #widget-area p {
	margin: 0;
}

/* .sidebarflyer — used only in sidebar-custom.php. Holds its own
   flyer image now that it has its own home instead of sharing
   .sidebargif with the gif image. height:auto for the same reason
   .sidebargif is: let the box grow to fit whatever the day's random
   flyer image's aspect ratio actually turns out to be. */
.sidebarflyer {
	height:auto;
	width:344px;
	margin-left: 3.4px;
}

.sidebarflyer img {
	height:100%;
	width:100%;
}

/* .boxpreview — used in loop-customcat.php's final generic
   `is_category()` branch — the catch-all thumbnail card for any
   category that doesn't have its own dedicated branch (vault,
   episodes, music, xzines, blog, merch, gifs all have their own;
   everything else falls through to this). This is also what zine
   posts actually render as right now, since the "xzines" typo
   means they fall through to here instead of their intended
   #fullwrap layout — see the to-do doc for that whole story. */
.boxpreview {
	background:#0F0F0F;
	height: 467px;
	width: 350.2px;
	padding-bottom: 15px;
}

.boxpreview img {
	max-width:100%;
	max-height:100%;
	margin:auto;
	display:block;
}

.boxpreview:hover img {
	opacity:.93;
}

.boxpreview:active img {
	opacity:1.0;
}

/* .gifpreview — used in loop-customcat.php's "gifs" category branch
   specifically (one step before the generic .boxpreview fallback
   above — gifs get their own dedicated thumbnail card). */
.gifpreview {
	background:#0F0F0F;
	height: 263.2px;
	width: 350.2px;
	padding-bottom: 0px;
}

.gifpreview img {
	max-width:100%;
	max-height:100%;
	margin:auto;
	display:block;
}

.gifpreview:hover img {
	opacity:.93;
}

.gifpreview:active img {
	opacity:1.0;
}

/* .thevault — layout wrapper used only in main.php (homepage vault
   listing). .vault3 / .epcon below are the equivalent wrappers for
   loop-customcat.php's category-archive listings — three similar
   "float-left list item" wrappers, one per template/context rather
   than one shared between them.
   margin:0 cancels the browser's default <figure> margin (1em 40px)
   so nothing shifts. */
.thevault {
	margin: 0;
	float: left;
	clear: right;
	padding: 0px 12px 0px 0px;
}

/* .vault3 and .epcon are <figure> elements (see
   loop-customcat.php) — margin:0 cancels the browser's default figure
   margin (1em 40px); .epcon's own margin-left:12.5px still wins for
   that one side since it's declared after (same rule, later
   declaration for the same longhand overrides the shorthand). */
.vault3 {
	margin: 0;
	float: left;
	clear: right;
	padding: 0px 0px 0px 12.5px;
}

.epcon {
	margin: 0;
	float: left;
	clear: right;
	margin-left: 12.5px;
}

/* .vhsl — the largest tape-spine size, used in loop-customcat.php's
   "episodes" category-archive branch (the wide single-column
   listing). 'scratch' font (see Custom Fonts above) renders the
   show-title text directly on top of each post's "vhs" custom-field
   background image. */
.vhsl {
	background-repeat: no-repeat;
	/* Used to be an inline style="" attribute in loop-customcat.php's
	   episodes branch, moved here so the /episodes Mobile + Tablet
	   Layout blocks further down can override it with a fluid
	   background-size without !important — same fix already applied
	   to .vhssm and .cart for the identical reason. */
	background-size: 1074px 191px;
	height: 191px;
	width: 1074px;
	font-family: 'scratch', monospace;
	font-size:62px;
	text-transform:uppercase;
	letter-spacing:0px;
	word-spacing:-1px;
	line-height:190px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
}

.vhsl  a {
	color: #303030;
}

.vhsl  a:hover {
	color: #E00000;
}

.vhsl  a:active {
	color: #ff4e00;
}

/* .vhs — the medium/standard tape-spine size, used in main.php
   (homepage episode listing). (eps.php, formerly also a consumer,
   has since been deleted as an orphaned template.)
   margin:0 cancels the browser's default <figure> margin (1em 40px)
   so nothing shifts. background-size moved here (main.php used to
   set it inline, redundantly) so the /Main Mobile + Tablet Layout
   blocks further down can override it with a fluid background-size
   without !important — same fix already applied to .vhssm/.vhsl/.cart
   for the identical reason. */
.vhs {
	margin: 0;
	background-repeat: no-repeat;
	background-size: 711px 136px;
	height: 136px;
	width: 711px;
	font-family: 'scratch', monospace;
	color: #303030;
	font-size:42px;
	text-transform:uppercase;
	letter-spacing:0px;
	word-spacing:-1px;
	line-height:135px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
}

.vhs a {
	color: #303030;
}

.vhs a:hover {
	color: #E00000;
}

.vhs a:active {
	color: #ff4e00;
}

/* .vhssm — the small/sidebar tape-spine size, used in main.php and
   loop-customcat.php's vault-category branch (the smaller spine
   thumbnails seen in vault listing grids and sidebars). */
.vhssm {
	background-repeat: no-repeat;
	background-size: 350.2px 67px;
	height: 67px;
	width: 350.2px;
	font-family: 'scratch', monospace;
	font-size:21px;
	text-transform:uppercase;
	letter-spacing:0px;
	word-spacing:-1px;
	line-height:64px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
}

.vhssm a {
	color: #303030;
}

.vhssm a:hover {
	color: #E00000;
}

.vhssm a:active {
	color: #ff4e00;
}


/* .vhs_sidebar — the sidebar-specific tape-spine size, used in
   sidebar-episodes.php and sidebar-vault.php (the spine thumbnails
   in the episode/vault sidebar lists, distinct from .vhssm which is
   the grid/listing version of a similarly small spine). */
.vhs_sidebar {
	background-repeat: no-repeat;
	padding-left:6px;
	margin-left:4px;
	height: 68px;
	width: 351px;
	font-family: 'scratch', monospace;
	letter-spacing:0px;
	color: #303030;
	font-size:80%;
	text-transform:uppercase;
	letter-spacing:-3px;
	word-spacing:-9px;
	line-height:68px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
	display: block;
}

/* .micro — layout wrapper used only in loop-customcat.php's "blog"
   category branch (wraps .cartspine/.cart below). */
.micro {
	float: left;
	clear: right;
	margin-left: 12.5px;
}

/* .cartspine / .cart below — the cassette-tape-style spine used for
   blog posts (loop-customcat.php's "blog" branch). The per-post
   artwork comes from a "cart" custom field (get_post_meta($post->ID,
   'cart', true)) — same per-post-image technique as the "vhs" field
   drives the .vhs/.vhssm/.vhs_sidebar family above, just for a
   different content type and a different field name. Unlike the much
   older "vhs"/"preview_img" fields, "cart" is a more recent addition
   and still the current, intentional way blog-post cassette art
   works — not a legacy leftover. */
.cartspine {
	font-family: 'MOM', monospace;
	background-repeat: no-repeat;
	text-decoration:none;
	display: block;
}

/* (Four `.cartspine a:*` link-color rules used to live here. They
   targeted an <a> INSIDE .cartspine — a structure that has never
   existed in the rendered DOM: .cartspine IS the anchor (and always
   was, even back when the old malformed markup was being auto-
   repaired by the browser). The colors that actually render come
   from `.cart a` below and the global link colors. Removed as
   confirmed-dead. */

.cart {
	background-repeat: no-repeat;
	/* Used to be an inline style="" attribute in loop-customcat.php's
	   blog branch, moved here so the /blog Mobile Layout block (see
	   that section further down) can override it with a fluid
	   background-size without needing !important — same fix already
	   applied to .vhssm's background-size for the same reason, see
	   the Files Touched table in Vault Work/HANDOVER.md. */
	background-size: 532px 138px;
	height: 138px;
	width: 532px;
	font-size:24px;
	text-transform:uppercase;
	letter-spacing:0px;
	word-spacing:-1px;
	line-height:24px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
}

.cart  p {
	color: #303030;
	font-size:14px;
	line-height:17px;
	padding-top: 2px;
	padding-left: 35px;
	padding-right: 35px;
	text-transform: none;
}

.cart  a {
	padding-top: 45px;
	color: #303030;
}

.cart  a:hover {
	color: #E00000;
}

.cart  a:active {
	color: #ff4e00;
}

/* Stray: this is .vhs_sidebar's hover state, but the rest of
   .vhs_sidebar lives much further up this section (search for the
   main .vhs_sidebar rule above) — it got separated from its own
   block at some point and ended up sitting here instead, in between the
   .cart family and .30yom below. Doesn't cause any visual problem
   (CSS doesn't care where in the file a rule for the same selector
   lives), just an example of the kind of organizational drift this
   file has accumulated — a candidate to relocate next to its parent
   rule whenever a reordering pass happens. */
.vhs_sidebar a:hover {
	color: #851f00;
}

/* .30yom — checked carefully: appears unused. A first pass looked
   promising (matched "30yom" on 3 pages) but every match turned out
   to be a coincidence — an uploaded file literally named
   "30yom.jpg" showing up in unrelated og:image tags and post-nav
   background styles, not this class being applied anywhere. No
   template references it either. Also worth knowing as a quirk:
   CSS class names aren't technically supposed to start with a
   digit per spec (it should be escaped, e.g. `.\33 0yom`) — browsers
   parse it leniently anyway, so this works today, but it's
   non-standard syntax, not just an unusual name. */
.30yom {
	background-repeat: no-repeat;
	height: 117px;
	width: 711px;
	font-family: 'scratch', monospace;
	color: #303030;
	font-size:42px;
	text-transform:uppercase;
	letter-spacing:0px;
	word-spacing:-1px;
	line-height:135px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
}

/* .vidspine — the most widely-used tape-spine wrapper class on the
   site: main.php, loop-customcat.php, eps.php, sidebar-vault.php,
   and sidebar-episodes.php all use it. It only handles the link/
   font behavior; the actual visual size comes from whichever of
   .vhsl/.vhs/.vhssm/.vhs_sidebar wraps it in a given template (see
   those above) — .vidspine and the size class work together on the
   same element. This class used to also come in
   15 numbered variants (.vidspine1 through .vidspine15) with fixed
   tape-brand background images — that whole numbered system was
   confirmed dead and removed, superseded by the per-post
   "vhs" custom-field image system these size classes now use instead. */
.vidspine {
	font-family: 'scratch', monospace;
	background-repeat: no-repeat;
	text-decoration:none;
	display: block;
}

/* (Six dead rules used to live here: four `.vidspine a:*` link
   colors — targeting an <a> inside .vidspine, a structure that has
   never existed in the rendered DOM, since .vidspine IS the anchor —
   and two `.vidspine:hover/:active img` opacity rules, though no
   image ever sits inside a spine link (the hover-preview images live
   in .preview/.gifpreview/.boxpreview, which have their own hover
   rules). The colors that actually render on spine titles come from
   `.vhsl a` / `.vhssm a` above. Removed as
   confirmed-dead. */


/* .30yomspine — same situation as .30yom above: no template
   references it, and no genuine inline usage found across the full
   site crawl either (this one didn't even have a coincidental
   filename match). Appears unused. Also has the same "class name
   starting with a digit" non-standard-but-browser-tolerated quirk
   as .30yom. */
.30yomspine{
	background-repeat: no-repeat;
	height: 117px;
	width: 711px;
	font-family: 'scratch', monospace;
	letter-spacing:0px;
	color: #303030;
	font-size:24px;
	text-transform:uppercase;
	letter-spacing:-2px;
	word-spacing:-9px;
	line-height:133px;
	vertical-align:text-middle;
	text-align:center;
	text-decoration:none;
}

/* .tray — used only in main.php (homepage). #fulltray below is a
   different, wider tray background used only in catsingle.php (the
   single vault/episode page) — similar concept, different template,
   different size, intentionally separate rather than shared. */
.tray {
	background-image: url(/assets/images/structure/blanktray.gif);
	background-repeat: no-repeat;
	height: 42px;
	width: 711px;
	display: block;
	text-align:center;
	float: left;
}

#fulltray {
	background-image: url(/assets/images/structure/full-tray.gif);
	background-repeat: no-repeat;
	margin: 0 auto;
	padding: 0px 0px 0px 184px;
	height: 79px;
	width: 1074px;
}


/* .wrap — used only in 404.php. This needs an aesthetic makeover. */

.wrap {


	height: 810px;
	width: 800px;
  }


.wrap {
	  margin: 0;
	  background-image: url(/assets/images/404/404.gif);
	  background-repeat: no-repeat;
	  background-size: cover;
	  width: 710px;
	  height: 500px;

}

/* .fingerbuttonleft / .fingerbuttonright below — the prev/next
   navigation buttons on catsingle.php (single vault/episode pages),
   sitting inside #fulltray above. These are the ones that used to
   point at a hardcoded production image URL
   (https://30mom.com/exim/fingerbutton*.png) before the CDN/
   self-hosting cleanup — now self-hosted in this theme's own
   images/ folder. */
.fingerbuttonleft {
	position: absolute;
	padding-top:8px;
	margin-left: 100px;
	height: 71px;
	width:96px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonleft a:link, .fingerbuttonleft a:visited{
	margin: 0px;
	background:url('/assets/images/structure/fingerbuttonleft.png') 0 0;
	height: 71px;
	width:96px;
	display: block;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonleft a:hover{
	background: url('/assets/images/structure/fingerbuttonleft.png') -96px 0;
	width:96px;
	height: 71px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonleft a:active{
	background: url('/assets/images/structure/fingerbuttonleft.png') -192px 0;
	height: 71px;
	width:96px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonright {
	position: absolute;
	padding-top:8px;
	margin-left: 504px;
	height: 71px;
	width:96px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonright a:link, .fingerbuttonright a:visited{
	margin: 0px;
	background:url('/assets/images/structure/fingerbuttonright.png') 0 0;
	height: 71px;
	width:96px;
	display: block;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonright a:hover{
	background: url('/assets/images/structure/fingerbuttonright.png') -96px 0;
	height: 71px;
	width:96px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.fingerbuttonright a:active{
	background: url('/assets/images/structure/fingerbuttonright.png') -192px 0;
	height: 71px;
	width:96px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

/* =Layout
   ------------------------------------------------------------
   Important to understand these four rules: `.one-column #content`
   etc. is NOT one element with both a class and an id. It's a
   descendant selector — two separate elements. It means "find the
   element with id="content", wherever it is, as long as it's nested
   somewhere inside an element with class="one-column"". So #content
   gets styled differently depending on which page-layout class its
   container happens to have — that's how one page can be a single
   centered column while another is full-width, using the same
   #content id everywhere but a different wrapper class around it.
-------------------------------------------------------------- */
/*
LAYOUT: Main Page
DESCRIPTION: One centered column a sidebar
*/

/* .one-column — set on #container by 404.php and main.php (the
   homepage), the two pages with a real sidebar (#leftmenu).
   #container itself (not #content) is the flex item here — see #main
   above — so it just needs to claim the row's remaining width after
   #leftmenu's own fixed width; #content inside it is then free to be
   plain width:auto (its default), no hardcoded number needed.
   This used to be a hardcoded `margin:61px 0 0 376px; width:752px` on
   #content instead — two numbers that had to be manually kept in sync
   with #topmenu's height and #leftmenu's width/position, and that had
   actually drifted out of sync (752px overflowed #main's 1100px box
   by 28px, silently clipped by #main's overflow:hidden — invisible,
   but that overflow was quietly giving floated content inside
   #content more width than #main's box itself ever showed).

   min-width:725px matters: flex:1 alone causes a real regression —
   main.php's paired vault-tape .thevault previews, two 362.2px-wide
   floats per row, need 724.4px to sit side by side, but flex:1's
   exact computed width (724.0px, confirmed via getBoundingClientRect)
   falls short by under half a pixel, just enough to push every one of
   them onto its own row instead of pairing up. 725px is that measured
   floor plus a hair of rounding margin, not an arbitrary guess —
   flex:1 still governs everything above that floor, so this only
   matters if the row ever gets this tight again. min-width:0
   (flexbox's own escape hatch from its default min-width:auto, which
   refuses to shrink a flex item below its content's natural width) is
   superseded by this explicit floor. */
.one-column#container {
	flex: 1;
	min-width: 725px;
}

/*
LAYOUT: Full Page
DESCRIPTION: One centered column a sidebar
*/

/* .full-page — set on #container only by full-page.php. margin-top
   used to be 61px, hand-tuned to clear #topmenu back when it was
   position:absolute and didn't push #main down on its own — removed
   now that #topmenu is real document flow (see above). */
.full-page #content {
	background: #0F0F0F;
	margin: 0px 0px 0px 13px;
	padding: 20px;
	width: 1034px;
	text-align: center;
}

/*
LAYOUT: Full width, no sidebar
DESCRIPTION: Full width content with no sidebar; used for attachment pages
*/

/* .single-attachment — different from the other three: this one
   isn't written anywhere in this theme's templates at all. It's a
   WordPress-core body class, added automatically to <body> when
   viewing an image attachment page. Since #content sits somewhere
   inside <body> on every page, it's automatically "inside"
   .single-attachment whenever WordPress decides this is an
   attachment page — no theme code has to add the class itself. */
.single-attachment #content {
	margin: 0 auto;
	width: 702px;
}

/*
LAYOUT: True Full width, no sidebar
*/

/* .single-30mom — the most widely-applied layout class: set on
   #container by category.php, narrow-text.php, artifacto.php,
   pics.php, single.php, and text.php. margin-top used to be 61px,
   same hand-tuned #topmenu-clearance hack as .full-page above —
   removed, no longer needed. */
.single-30mom #content {
	margin: 0;
	width: 1100px;
}

/* =Fonts
   ------------------------------------------------------------
   This section is a leftover stock-Twenty-Fifteen pattern: a big
   batch of selectors all set to one font, mixing genuinely-used
   selectors with several that don't exist anywhere in this
   theme's actual output. One confirmed-dead entry has already been
   removed from the list below (#site-info) — here's the full picture
   of what's left,
   checked against every top-level template, inc/template-tags.php
   (where several of these are generated by PHP functions rather
   than written as literal markup), and the full site crawl:

   Genuinely used: .entry-content/.entry-meta/.entry-title/
   .entry-utility (content.php, content-page.php, content-link.php,
   content-search.php, loop.php, image.php), .page-title (archive.php,
   content-none.php, search.php), .navigation (archive.php, search.php,
   loop.php, sidebar.php, image.php), .reply (404.php, artifacto.php —
   comment-reply links), .widget-title (generated by register_sidebar()
   in functions.php — real whenever any sidebar widget has a title).

   Real, but content/state-dependent (won't show up in a static crawl
   unless the right condition is true on the page you happen to
   check): #respond and .form-allowed-tags (both part of comment_form()'s
   default output in comments.php — only render when comments are
   open), .pingback (wp_list_comments() could render this, but only
   if a post actually has a pingback).

   Appears genuinely unused — no matching markup anywhere, not even
   inside customizer.php's generic boilerplate: #access (this theme's
   custom header.php never uses the stock #access nav wrapper),
   #cancel-comment-reply-link, #site-title (no element with this id
   exists in this theme's header.php). .wp-caption-text is the one
   genuine unknown — only appears in customizer.php boilerplate, would
   need an actual image-caption block in post content to confirm
   either way (same bucket as the other "WP-core, content-dependent"
   classes noted in the to-do doc). */
body,
input,
textarea,
.page-title span,
.pingback {
	font-family: 'MOM', monospace;
	color: #282828;
	font-size: 1.2em;
	font-weight: normal;
	line-height: 1.526em;
}

#cancel-comment-reply-link,
.form-allowed-tags,
.entry-content label,
.entry-content tr th,
.entry-content thead th,
.entry-meta,
.entry-title,
.entry-utility,
#respond label,
.navigation,
.page-title,
.pingback p,
.reply,
.widget-title,
.wp-caption-text {
	font-family: 'MOM';
}
input[type=submit] {
	font-family: 'MOM', monospace;
}
pre {
	font-family: 'MOM', monospace;
}
code {
	font-family: 'MOM', monospace;
}


/* =Structure
-------------------------------------------------------------- */

/* The main theme structure — #wrapper is the outermost page
   container, written in header.php/artifacto.php/404.php as
   `<div id="wrapper" class="hfeed">`. That's one element with both
   an id (this CSS hook) and a class (hfeed — a now-mostly-obsolete
   "this page is a feed of entries" microformat marker from the
   2008-2012 era, harmless, does nothing visually, not styled by
   anything here).

   This rule was two separate, adjacent #wrapper declarations (the
   plain accidental kind of duplicate, not the intentional
   #mobiletopmenu-style split) — merged into one.
   The old second rule's margin-top/margin-bottom: 0 were redundant
   (margin: 0 auto already zeroes top/bottom), and its `padding: 0 0px`
   is just `padding: 0` — so the merge changed no computed value. */
#wrapper {
	margin: 0 auto;
	width: 1100px;
	background-image:url('/assets/images/structure/rackbars.png');
	background-repeat:repeat-y;
	padding: 0;
}


/* =Global Elements
-------------------------------------------------------------- */

/* (Removed a redundant second `body { background: #000000 url('') repeat; }`
   rule that used to be here. The black background is already set by
   the primary body rule in the SITE-WIDE RESET & BASE STYLES section up
   top; `repeat` is the CSS default and the empty `url('')` loads no image,
   so this rule set nothing the first one didn't — its removal is a no-op.) */

hr {
	background-color: #585858;
	border: 0;
	clear: both;
	height: 1px;
	width: 90%;
}

/* ======================= */
/* Notepaper */
/* Used directly in post content, not applied by any template — one
   of the most-used custom classes on the site (50+ matches across
   vault posts). Renders as a handwritten-note/
   blockquote card for fan testimonials and quotes; .quote-by below
   is the attribution line inside it. Do not flag as dead without
   re-crawling every published post first. */
/* ======================= */
.notepaper {
  position: relative;
  margin: 1rem auto;
  padding: 0 1.5rem 0.3125rem 0.9375rem; /* 0 15px 5px 15px → rem */
  width: 31.25rem; /* 500px → rem (500/16 = 31.25) */
  color: #6a5f49;
  text-shadow: 0 1px 1px white;
  background-color: #fefff5;
  background-image: 
    radial-gradient(circle farthest-corner at center, 
      rgba(255,255,255,0.7) 0%, 
      rgba(255,255,255,0.1) 90%
    ),
    repeating-linear-gradient(
      transparent 0 29px, 
      rgba(239,207,173,0.7) 29px 30px
    );
  border: 1px solid rgba(195,186,170,0.9);
  box-shadow: 
    inset 0 1px rgba(255,255,255,0.5), 
    inset 0 0 5px #d6ccb8, 
    0 0 1px rgba(0,0,0,0.1), 
    0 2px rgba(0,0,0,0.02);
  box-sizing: border-box; /* Inherits from universal reset */
}

.notepaper::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 2.75rem; /* 28px → rem (28/16 = 1.75rem) + 15px padding (0.9375rem) */
  width: 2px;
  border-left: 2px solid rgba(239,207,173,0.9);
}

/* Background rotation effect */
.notepaper::after {
  content: '';
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(242,246,193,0.9);
  border: 1px solid rgba(170,157,134,0.7);
  transform: rotate(2deg);
}

/* Quote attribution */
.notepaper .quote-by {
  font-family: 'MOM', monospace;
  display: block;
  padding-left: 2.5rem; /* 40px → rem */
  text-align: left;
  font-size: 0.625rem; /* 10px → rem */
  font-style: italic;
  color: #84775c;
  line-height: 1.2;
}
/* =Content
   ------------------------------------------------------------
   Stock Twenty-Fifteen "blog content area" styling — generic
   typography defaults for anything inside #content (which exists
   on every page), plus the .entry-title/.entry-meta/.page-title/
   .hentry family already confirmed genuinely used back in the
   =Fonts section above (content.php, content-page.php, loop.php,
   archive.php, search.php, etc). One content-dependent exception
   worth knowing: .home .sticky only ever matters if a "sticky" post
   exists and the homepage is showing the blog index — a real
   WordPress core feature, just not something a static crawl can
   confirm without an actual sticky post to find.
-------------------------------------------------------------- */

/* #main is a plain block — it used to be display:flex itself
 * briefly, but that broke as soon as a third element needed to stack
 * above the sidebar+content pair (see .main-columns below for the
 * full story and why that responsibility moved to a dedicated
 * wrapper instead of living here). Keep it plain; put layout logic
 * for #main's *children* in their own rules, not here.
 */
#main {
	clear: both;
	overflow: hidden;
	padding: 0 0 0 0;
}

/* .main-columns — wraps #leftmenu + #container on the pages that have
 * a real sidebar (main.php, main-im.php, 404.php) and is what
 * actually lays them out side by side. This used to be display:flex
 * directly on #main — moved to its own wrapper after a real,
 * live-caught bug: main-im.php needs a third block
 * (.flex-im, the Infinite M/IMC iframes) to stack ABOVE this pair, and
 * making #main itself flex+flex-wrap:wrap to accommodate that broke
 * something unrelated and much worse — #container's floated vault-tape
 * previews (.thevault) stopped pairing up two-per-row and collapsed
 * into a single long column, because flex-wrap's line-fitting
 * calculation used #container's floated content's own intrinsic width
 * rather than respecting its resolved flex size. Confirmed by testing
 * flex-wrap:nowrap in isolation, which immediately fixed it. Rather
 * than fight that interaction, .flex-im now just sits BEFORE this
 * wrapper as a plain block (no flex-basis needed either — see its own
 * rule) and stacks above it via ordinary document flow, the same way
 * #topmenu pushes #main down: no wrapping, no competing flex line,
 * nothing left to interact badly.
 *
 * align-items:flex-start (rather than flex's stretch default) keeps
 * each child only as tall as its own content — #leftmenu and
 * #container are rarely the same height, and stretching one to match
 * the other would just be a new kind of magic-number-free but still
 * unintended coupling.
 *
 * gap:12.8px reproduces a real visual detail, not just spacing for
 * its own sake: #wrapper's background (/assets/images/structure/rackbars.png, a 1100px-
 * wide strip of rack-mount bolt/rail art tiled vertically) is mostly
 * hidden behind opaque foreground content, but a sliver of one bar
 * has always shown through right in the seam between #leftmenu and
 * #container, working as a visual divider between them. That sliver
 * used to be a side effect of #leftmenu's box (ending at 13px +
 * 350.2px = 363.2px) and #content's old hardcoded margin-left:376px
 * landing 12.8px apart — 12.8px reproduced here exactly, on purpose.
 * #container's own flex:1 (see .one-column#container below) already
 * fills 100% of whatever's left after this gap, which is also what
 * fixes the page's right edge automatically: the old hardcoded
 * width:752px on #content drifted the whole block 28px past this
 * row's actual 1100px width, invisibly clipped by #main's
 * overflow:hidden — a well-hidden bug this incidentally corrects.
 */
.main-columns {
	display: flex;
	align-items: flex-start;
	gap: 12.8px;
}

#content p,
#content ul,
#content ol,
#content dd,
#content pre,
#content hr {
	margin-bottom: auto;
}
#content ul ul,
#content ol ol,
#content ul ol,
#content ol ul {
	margin-bottom: 0;
}
#content pre,
#content kbd,
#content tt,
#content var {
	line-height: 21px;
}
#content code {
	font-size: 13px;
}
#content dt,
#content th {
	color: #000;
}

#content table {
	border: 1px solid #e7e7e7;
	margin: 0 -1px 0px 0;
	text-align: left;
	width: 100%;
}
#content tr th,
#content thead th {
	color: #888;
	line-height: 18px;
	padding: 9px 24px;
}
#content tr td {
	border-top: 1px solid #e7e7e7;
}
#content tr.odd td {
	background: #f2f7fc;
}
.hentry {
	margin: 0 0 48px 0;
}

/* WordPress's post_class() always adds "hentry" on a singular page,
   so /gallery's <article> picks up the generic 48px post-spacing
   above meant for actual blog posts — not wanted on this page, whose
   .albumgallery content is meant to sit flush against the rack's
   bottom edge. Scoped to articles wrapping .albumgallery specifically
   so search results and ordinary posts/pages keep their real 48px
   .hentry spacing (confirmed live on /?s= search results). */
article:has(> .albumgallery) {
	margin-bottom: 0;
}
.home .sticky {
	background: #f2f7fc;
	border-top: 4px solid #000;
	margin-left: -20px;
	margin-right: -20px;
	padding: 18px 20px;
}
.single .hentry {
	margin: 0 0 36px 0;
}
.page-title {
	font-size: 14px;
	margin: 0 0 36px 0;
}
.page-title span {
	font-size: 16px;
	font-style: italic;
	font-weight: normal;
}
.page-title a:link,
.page-title a:visited {
	color: #ff3c00;
	text-decoration: none;
}
.page-title a:active,
.page-title a:hover {
	color: #ff4b33;
}
#content .entry-title {
	color: #000;
	font-size: 21px;
	line-height: 1.3em;
	margin-bottom: 0;
}
.entry-title a:link,
.entry-title a:visited {
	color: #ff3c00;
	text-decoration: none;
}
.entry-title a:active,
.entry-title a:hover {
	color: #ff4b33;
}
.entry-meta {
	color: #888;
	font-size: 12px;
}
.entry-meta abbr,
.entry-utility abbr {
	border: none;
}
.entry-meta abbr:hover,
.entry-utility abbr:hover {
	border-bottom: 1px dotted #666;
}
/* .entry-content fieldset/input/select/label etc. below — generic
   styling for any HTML form that ends up inside post content (the
   comment form is the realistic case here, via comments.php's
   comment_form() call — content/state-dependent like .entry-meta
   above, only renders when comments are open on a page you check).
   .entry-content blockquote.left/.right are a WP-core convention
   for floating a blockquote left/right within post content via the
   "Left"/"Right" alignment option some editors expose — would only
   appear if a post actually used that option. */
.entry-content,
.entry-summary {
	clear: both;
	padding: 24px 0 0 0;
}
#content .entry-summary p:last-child {
	margin-bottom: 12px;
}
.entry-content fieldset {
	border: 1px solid #e7e7e7;
	margin: 0 0 24px 0;
	padding: 24px;
}
.entry-content fieldset legend {
	background: #fff;
	color: #000;
	padding: 0 24px;
}
.entry-content input {
	margin: 0 0 24px 0;
}
.entry-content input.file,
.entry-content input.button {
	margin-right: 24px;
}
.entry-content label {
	color: #888;
	font-size: 12px;
}
.entry-content select {
	margin: 0 0 24px 0;
}
.entry-content sup,
.entry-content sub {
	font-size: 10px;
}
.entry-content blockquote.left {
	float: left;
	margin-left: 0;
	margin-right: 24px;
	text-align: right;
	width: 33%;
}
.entry-content blockquote.right {
	float: right;
	margin-left: 24px;
	margin-right: 0;
	text-align: left;
	width: 33%;
}
/* .page-link — WordPress's built-in post-pagination links (the
   "1 2 3 Next" style navigation that appears when a post uses the
   <!--nextpage--> tag to split across multiple pages). Real core
   feature, content-dependent — only shows up if a post actually
   uses page-splitting, which none of the crawled pages happened to. */
.page-link {
	clear: both;
	color: #000;
	margin: 0 0 22px 0;
	word-spacing: 0.5em;
}
.page-link a:link,
.page-link a:visited {
	background: #f1f1f1;
	color: #ff3c00;
	font-weight: normal;
	padding: 0.5em 0.75em;
	text-decoration: none;
}
.home .sticky .page-link a {
	background: #d9e8f7;
}
.page-link a:active,
.page-link a:hover {
	color: #ff4b33;
}
/* body.page .edit-link — WordPress core's "Edit" link that appears
   on pages, but only to logged-in users with edit permission.
   Invisible to a logged-out crawl by design, not a sign it's
   missing or broken. */
body.page .edit-link {
	clear: both;
	display: block;
}

.entry-utility {
	clear: both;
	color: #888;
	font-size: 12px;
	line-height: 18px;
}
.entry-meta a,
.entry-utility a {
	color: #888;
}
.entry-meta a:hover,
.entry-utility a:hover {
	color: #ff4b33;
}
/* =Asides
   ------------------------------------------------------------
   WordPress's "Aside" post format and a hypothetical "asides"
   category — both core/theme features that only render this
   specific markup if a post actually uses the Aside post format,
   or a category literally named "asides" exists and is being
   viewed on the homepage. Neither has shown up in the full site
   crawl, but that only proves no such content was crawled, not
   that the feature is dead — same unresolved bucket as the other
   WP-core content-dependent classes noted in the to-do doc.
-------------------------------------------------------------- */

.home #content .format-aside p,
.home #content .category-asides p {
	font-size: 14px;
	line-height: 20px;
	margin-bottom: 10px;
	margin-top: 0;
}
.home .hentry.format-aside,
.home .hentry.category-asides {
	padding: 0;
}
.home #content .format-aside .entry-content,
.home #content .category-asides .entry-content {
	padding-top: 0;
}


/* =Gallery listing
   Same situation as Asides above — WordPress's "Gallery" post
   format / a hypothetical "gallery" category. Don't confuse this
   WP-core .format-gallery/.category-gallery pair with this site's
   own custom .gifpreview/.boxpreview thumbnail system (Tape-Spine
   & Thumbnail Components section, much earlier in this file) — that
   custom system is what loop-customcat.php actually uses for the
   real gallery/gifs archive listings on this site; these WP-core
   classes are a separate, unconfirmed, possibly-unused layer.
-------------------------------------------------------------- */

.format-gallery .size-thumbnail img,
.category-gallery .size-thumbnail img {
	border: 10px solid #f1f1f1;
	margin-bottom: 0;
}
.format-gallery .gallery-thumb,
.category-gallery .gallery-thumb {
	float: left;
	margin-right: 20px;
	margin-top: -4px;
}
.home #content .format-gallery .entry-utility,
.home #content .category-gallery .entry-utility {
	padding-top: 4px;
}


/* =Attachment pages
   Styling for WordPress's built-in attachment pages (the dedicated
   page WordPress generates for a single uploaded image) — the
   `\2190`/`\2192` are literal left/right arrow characters for the
   prev/next image navigation links. Real core feature; only
   renders when viewing an attachment page directly, which the
   site's own templates don't appear to link to anywhere obvious
   (this site uses its own custom gallery/thumbnail system instead,
   see the note above) — likely rarely if ever hit by a real visitor.
-------------------------------------------------------------- */

.attachment .entry-content .entry-caption {
	font-size: 50%;
	margin-top: 14px;
}
.attachment .entry-content .nav-previous a:before {
	content: '\2190\00a0';
}
.attachment .entry-content .nav-next a:after {
	content: '\00a0\2192';
}


/****************************
    WP Images
**********************************************/ 

/*
Resize images to fit the main content area.
- Applies only to images uploaded via WordPress by targeting size-* classes.
- Other images will be left alone. Use "size-auto" class to apply to other images.
*/

/* img.attachment-full — checked templates and the full crawl: no
   match anywhere. Appears unused (the attachment template,
   image.php, doesn't output this class). */
img.attachment-full {
	margin:0;
	display: block;
}


/* size-auto/size-full/size-large/size-medium are WordPress's
   automatic image-size classes, added to <img> tags based on which
   size an editor picked when inserting an image. size-full/large/
   medium are confirmed genuinely used across the site (real,
   common WordPress behavior for any inserted image); size-auto
   specifically — checked everywhere, no match — appears unused. */
img.size-auto,
img.size-full,
img.size-large,
img.size-medium,
.attachment img {
	max-width: 100%; /* When images are too wide for containing element, force them to fit. */
	height: auto; /* Override height to match resized width for correct aspect ratio. */
}

/* .alignleft/.alignright/.aligncenter below — WordPress's automatic
   image-alignment classes (added based on the alignment an editor
   picks when inserting an image). All three confirmed genuinely
   used across the site — these are about as fundamental to WP
   image handling as it gets. */
.alignleft,
img.alignleft {
	display: inline;
	float: left;
	margin-right: 24px;
	margin-left: 24px;
	margin-top: 4px;
}
.alignright,
img.alignright {
	display: inline;
	float: right;
	margin-left: 24px;
	margin-right: 24px;
	margin-top: 4px;
}
.aligncenter,
img.aligncenter {
	clear: both;
	display: block;
	margin-left: auto;
	margin-right: auto;
}
img.alignleft,
img.alignright,
img.aligncenter {
	margin-bottom: 5px;
}

/* Used directly in post content, not applied by any template — a
   very common image-float/spacing helper (60+ matches across posts),
   typically on small inline thumbnail links. */
.goleft {
	display: inline;
	margin-right: 10px;
	margin-left: 10px;
	margin-top: 4px;
	margin-bottom: 4px;
}

/* Used directly in post content, not applied by any template —
   small bordered caption/image card, seen on at least one post. */
.smaption {
	background: transparent;
	font-family: 'traveling';
	border-style: solid;
	border-width: 1px;
	border-color: #36454F;
	font-size: 85%;
	line-height: 22px;
	max-width: 196px;
	padding: 5px;
	margin: 10px;
	text-align: center;
	float: left;
}

.smaption img {
	margin: 0px 0px 0;
	border-style: double;
	border-color: #71797E;
	border-width: 2px;
}

/* .caption — checked templates and the full crawl (the one "caption"
   match in the raw crawl turned out to be an unrelated JSON key
   inside embedded audio-player data, not this class): appears
   unused. Not to be confused with .wp-caption right below, which is
   the real, active WordPress-core caption wrapper and is a
   completely separate class despite the similar name. */
.caption {
	font-family: 'traveling';
}

/* .wp-caption — WordPress core's automatic wrapper around any image
   that has a caption set in the editor. Confirmed genuinely used
   across the site. */
.wp-caption {
	background: #F8F0E3;
	border-style: solid;
	border-width: 1px;
	border-color: #36454F;
	font-size: 75%;
	line-height: 22px;
	max-width: 640px !important; /* prevent too-wide images from breaking layout */
	padding: 10px;
	text-align: center;
}

.wp-caption em {
	font-size: 100%;
}

.wp-caption img {
	margin: 0px;
	border-style: double;
	border-color: #71797E;
	border-width: 0px;
}

.wp-caption p.wp-caption-text {
	color: #888;
	font-size: 50%;
	margin: 5px;
}

/* .wp-smiley — WordPress core's auto-converted smiley images (when
   text like ":)" gets turned into an emoji image). Content-
   dependent, no template reference expected; didn't show up in the
   crawl, can't confirm either way without a post that uses one. */
.wp-smiley {
	margin: 0;
}
/* .gallery and its descendants below — WordPress's built-in
   [gallery] shortcode output. Content-dependent like .wp-smiley
   above (no template generates this, only the shortcode does) —
   and worth noting this site has its own separate custom gallery
   system (.gifpreview/.boxpreview, see Tape-Spine & Thumbnail
   Components much earlier in this file) that loop-customcat.php
   actually uses for real archive listings, so even if some posts
   do use the [gallery] shortcode in-content, it's not the site's
   primary gallery mechanism. */
.gallery {
	margin: 0 auto 18px;
}
.gallery .gallery-item {
	float: left;
	margin-top: 0;
	text-align: center;
	width: 33%;
}
.gallery-columns-2 .gallery-item {
	width: 50%;
}
.gallery-columns-4 .gallery-item {
	width: 25%;
}
.gallery-columns-2 .attachment-medium {
	max-width: 92%;
	height: auto;
}
.gallery-columns-4 .attachment-thumbnail {
	max-width: 84%;
	height: auto;
}
.gallery .gallery-caption {
	color: #888;
	font-size: 10px;
	margin: 0 0 12px;
}
.gallery dl {
	margin: 0;
}
/* Border on WP gallery-shortcode images. (There used to be a second,
   earlier `.gallery img` rule with a 2px #cfcfcf border that this one
   silently overrode — same specificity, later rule wins — so it had
   zero visual effect; it was removed in the 2026 cleanup. This 10px
   #f1f1f1 border is and always was the one that actually rendered.) */
.gallery img {
	border: 10px solid #f1f1f1;
}
.gallery br+br {
	display: none;
}
#content .attachment img {/* single attachment images should be centered */
	display: block;
	margin: 0;
}

/****************************
    End WP Images
**********************************************/ 


/****************************
    WP Navigation
    .navigation (confirmed used: archive.php, search.php, loop.php,
    sidebar.php, image.php — see =Fonts section earlier for the
    full check) is the older/more confusing styling for post
    pagination — #nav-above/#nav-below below are the wrapper ids
    around it, both confirmed real via loop.php.
**********************************************/

.navigation {
	color: #888;
	font-size: 12px;
	line-height: 18px;
	overflow: hidden;
}
.navigation a:link,
.navigation a:visited {
	color: #ff3c00;
	text-decoration: none;
}
.navigation a:active,
.navigation a:hover {
	color: #ff4b33;
}
.nav-previous {
	float: left;
	width: 50%;
}
.nav-next {
	float: right;
	text-align: right;
	width: 50%;
}
/* #nav-above's two rules here are intentional, not a conflicting
   duplicate like .gallery img above — the properties don't overlap
   (margin in the first, display in the second), and the third rule
   right after conditionally flips display back to visible (.paged/
   .single body classes — i.e. only show this nav block on a
   paginated archive or a single post, hidden everywhere else by
   default). Three cooperating rules, not redundant ones. */
#nav-above {
	margin: 0 0 18px 0;
}
#nav-above {
	display: none;
}
.paged #nav-above,
.single #nav-above {
	display: block;
}
#nav-below {
	margin: -18px 0 0 0;
}

/****************************
    End WP Navigation
**********************************************/ 

/* Old reminder note: border-collapse/border-spacing here is the
   CSS-only way to remove table cell spacing, but the original
   author also noted the HTML markup itself still needs a literal
   cellspacing="0" attribute as a fallback — a leftover concern
   from much older email-client/browser compatibility, not relevant
   to any current browser, but harmless to leave as a note. */

table {
	border-collapse: collapse;
	border-spacing: 0;
}

/* Nested ordered-list numbering style: top level uses 1,2,3 (decimal),
   then A,B,C, then i,ii,iii, then a,b,c for each deeper level of
   nesting — a classic outline-numbering convention, applied here in
   case any post content uses a real multi-level numbered list. */
ol {
	list-style: decimal;
	margin: 0 0 18px 1.5em;
}
ol ol {
	list-style: upper-alpha;
}
ol ol ol {
	list-style: lower-roman;
}
ol ol ol ol {
	list-style: lower-alpha;
}
ul ul,
ol ol,
ul ol,
ol ul {
	margin-bottom: 0;
}

dl {
	margin: 0 0 24px 0;
}

dt {
	font-weight: bold;
}

dd {
	margin-bottom: 18px;
}

strong {
	font-weight: bold;
}

del {
	text-decoration: line-through;
}


/****************************
    Footer
    #footer is written in footer.php — a short, fully custom footer
    (just the copyright line), nothing like the original Twenty
    Fifteen footer this theme was based on. This is the site-wide
    "30 MINUTES OF MADNESS AND 30MOM © LETHAL FINGER LLC, 1992-..."
    line that appears on every single page — and the rule that uses
    the '30MOMRegular' font (see Custom Fonts at the top of this
    file for the full story of confirming this usage).
**********************************************/

#footer {
	position: relative;
	background-image: url(/assets/images/structure/footer.png);
	background-repeat: no-repeat;
	height: 46px;
	width: 1100px;
	margin-bottom: 0px;
	text-align: center;
}

/* #footer p — dead CSS: footer.php's real markup is
   <div class="cg cg-footer">, never a <p>, so this never matches
   anything. Left in place rather than deleted (out of scope for this
   fix), but don't mistake it for the rule that's actually
   centering/styling the copyright line — that's .cg-footer below. */
#footer p {
	font-family: 'quanta', monospace;
	color: #ff3c00;
	font-size: 16px;
	font-weight: 700;
	letter-spacing: 1.2px;
	text-transform:uppercase;
	text-shadow: 1px 1px 4px #ff3c00, -1px -1px 4px #ff3c00;
	line-height: 46px;
	margin: 0px;
}

/* Shared centering mechanism for .cg-footer, unscoped so desktop,
   mobile, and tablet all use one copy (breakpoint blocks below only
   set font-size). Scoped to #footer .cg-footer, not bare .cg-footer —
   .cg's own base rule (see "Base CG Effect") also sets
   position:relative at equal specificity and sits later in the file,
   so it would otherwise win the position property back. line-height:
   normal + white-space:pre matter beyond looks: a fixed line-height
   fights an auto-height flex child, and 'pre' stops flex from
   trimming the space between the year and "LETHAL" once it splits
   this into three anonymous items. */
#footer .cg-footer {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	line-height: normal;
	white-space: pre;
	/* .cg's own cg-colordrift animation carries a constant filter:blur(1.4px)
	   (see "Base CG Effect" further down) — a fixed px radius, not relative
	   to font-size. .cg-footer's own font-size shrinks as low as 8px on
	   mobile (clamp() below) and ~11px on tablet (vw below), where a flat
	   1.4px blur radius is disproportionately large relative to the glyph
	   strokes and reads as smeared/too-blurry text — reported live by the
	   owner. --cg-blur here overrides the keyframes' own var(--cg-blur,
	   1.4px) fallback, in em so it scales with .cg-footer's own font-size
	   at every breakpoint: 0.0875em resolves to exactly 1.4px at this
	   element's 16px desktop size (pixel-identical to before this fix,
	   confirmed by the math, not just assumed) and shrinks proportionally
	   below that, instead of needing a separate override duplicated in
	   each breakpoint block below. Scoped to .cg-footer specifically (not
	   the shared, unscoped .cg base rule) so .cg-sidebar and
	   #vaultHeaderCategoryLabel.cg's own blur are untouched. */
	--cg-blur: 0.0875em;
	/* align-items:center above centers the LINE BOX, not the visible glyph
	   ink — for this all-caps/no-descender copyright line, quanta's own
	   ascent metric carries more headroom above cap-height than its descent
	   metric carries below the baseline, so the centered line box leaves
	   more dark space above the text than below it (owner-reported live:
	   "too much dark above compared to the dark below it"). NOT a static
	   transform/translateY fix — .cg's own cg-jitter animation already
	   drives `transform` on this element (see "Base CG Effect" further
	   down), so a static transform here would get overridden mid-jitter,
	   same reasoning already documented for the centering mechanism itself
	   above. padding-bottom on the flex item shifts its centered position
	   upward without touching `transform`. 0.2em is a first-pass estimate
	   (2.4px at this element's 16px desktop size, scaling proportionally
	   at every breakpoint like --cg-blur above) — re-check live and adjust
	   this value up/down if it's still off. */
	padding-bottom: 0.2em;
}

/****************************
    End Footer
**********************************************/ 

/****************************
    Widget Areas
    .widget-area here styles WordPress's real, native widget-area
    system (register_sidebar() + dynamic_sidebar()), as opposed to
    this site's other, much more common pattern of hand-coded
    sidebar partials like sidebar-custom.php.

    Sidebars are deliberately disabled site-wide except on the
    homepage ("Main" page). The intended mechanism was a
    category-based switcher in single.php
    (`get_sidebar('episodes')`/`get_sidebar('vault')`/
    `get_sidebar('custom')`), but instead of being cleanly removed,
    every branch was just commented out, leaving execution to fall
    through to a bare `get_sidebar();` that loads the stock
    sidebar.php and calls `dynamic_sidebar('sidebar-2')` — a sidebar
    ID that was never registered (only 'sidebar-1' was, in
    functions.php), so it silently renders nothing. Net effect: every
    single post page (vault, episodes, blog, zines, gifs, flyers,
    merch, music) shows an empty, non-functional widget-area wrapper
    — not a bug, just an intentional feature disabled in a kludgey
    rather than clean way.

    sidebar-vault.php and sidebar-episodes.php — both fully written,
    complete files with real content (vault counter, episode list +
    Facebook widget) — are the leftover sidebars from that original
    plan. Kept in case sidebars come back for specific sections, with
    no current plan to reactivate them. Candidates for a future
    cleanup pass (either delete for good, or move to a clearly marked
    "kept just in case" location) — not something to act on now.
**********************************************/

.widget-area ul {
	list-style: none;
	margin-left: 0;
}
.widget-area ul ul {
	list-style: square;
	margin-left: 1.3em;
}
.widget-area select {
	max-width: 100%;
}
.widget_search #s {/* This keeps the search inputs in line */
	width: 60%;
}
.widget_search label {
	display: none;
}
.widget-container {
	margin: 0 0 18px 0;
}

/* .widget_rss / .widget_search above and below — styling for
   specific widget TYPES (an RSS-feed widget, the search widget).
   Since the only reachable widget area (main.php's sidebar-custom.php,
   via the real `register_sidebar('sidebar-1')`) is hand-coded HTML
   rather than a true dynamic_sidebar() output, these widget-type
   classes would only ever apply if sidebar-1 actually had an RSS or
   Search widget assigned to it in wp-admin — unconfirmed either way
   from code alone. */
.widget_rss a.rsswidget {
	color: #000;
}
.widget_rss a.rsswidget:hover {
	color: #ff4b33;
}
.widget_rss .widget-title img {
	width: 11px;
	height: 11px;
}

/* Main sidebars */
#main .widget-area ul {
	margin-left: 0;
	padding: 0 20px 0 0;
}
#main .widget-area ul ul {
	border: none;
	margin-left: 1.3em;
	padding: 0;
}

/****************************
    End Widget Areas
**********************************************/ 

/* Tumblr-only styles removed — they served an external
   spinoff Tumblr blog, not this site. Full copy preserved in
   tumblr/style.css for reference until that's relocated out of the
   theme entirely. */

/* =Mobile Safari ( iPad, iPhone and iPod Touch )
   ------------------------------------------------------------
   -webkit-text-size-adjust is an old iOS-Safari-specific property:
   without it, mobile Safari auto-boosts font sizes on certain text
   blocks to make them more readable when a page is zoomed out
   (exactly the "shrink the whole desktop layout to fit" behavior
   this site relies on instead of a viewport tag — see the
   #mobiletopmenu note further down). These rules dial that
   auto-boost up or down per element so the auto-resizing doesn't
   make things look wrong. (#access and #site-description — stock
   Twenty Fifteen header ids this theme's customized header.php never
   outputs — were trimmed from this cluster.)
   .entry-meta/.entry-utility/.navigation/.widget-area are all
   confirmed real elsewhere in this file.

   Section name aside, most of what follows below this banner isn't
   actually Mobile-Safari-specific — it's just where the
   #mobiletopmenu visibility-toggle and the zinebg/blogtext
   restoration (see their own comments) ended up appended over time.
-------------------------------------------------------------*/

/* If in mobile screen with maximum width 479px. The iPhone screen resolution is 320x480 px (except iPhone4, 640x960) */

pre {
	-webkit-text-size-adjust: 140%;
}
code {
	-webkit-text-size-adjust: 160%;
}
.entry-meta,
.entry-utility,
.navigation,
.widget-area {
	-webkit-text-size-adjust: 120%;
}
/* (#access and a #site-description rule were trimmed from this
   cluster — stock Twenty Fifteen ids this theme's custom
   header.php never outputs, so they matched nothing.) */

/* Text meant only for screen readers — a real, important
   accessibility class, confirmed genuinely used across many
   templates (functions.php, archive.php, content*.php, search.php,
   image.php, sidebar.php, inc/template-tags.php). Visually hides
   text (pushed far off-screen) while keeping it available to
   screen readers — e.g. labels that sighted users don't need to
   see but screen-reader users do. */

.screen-reader-text {
	position: absolute;
	left: -9000px;
}

/* #zinebg and the .blogtext family below are used directly in post
   content, not applied by any template — the zine-formatted-post
   layout (tiled paper background + typeset text styles). A full-site
   crawl showed they're genuinely in use; don't flag as dead from
   template-source checks alone. */
#zinebg  {
	background: url('/assets/images/structure/paper-tiled.gif') 0px 0;
	width: 99.8%;
}

.blogtext {
	font-family: 'traveling';
	width: 90%;
	text-align:left;
	margin-left: 35px;
	padding-bottom: 30px;
	font-size: 24px;
	line-height: 32px;
}

.blogtext p, .blogtext span {
	font-family: 'traveling';
	font-size: 24px;
}

/* NOT scoped to .blogtext, unlike its siblings above — this used to be
   part of a broken selector list (`.blogtext p, span, em`, missing the
   .blogtext qualifier on span AND em) that accidentally matched every
   <em> on the entire site. A full-site content crawl found
   ~58 real italicized captions/dates/quote-attributions across vault,
   episodes, zines, music, and blog posts that genuinely render in this
   font today because of that bug — unlike span (nothing outside
   .blogtext turned out to depend on it), so em is kept sitewide on
   purpose here, pixel-identical to before, just no longer accidental. */
em {
	font-family: 'traveling';
	font-size: 24px;
}

.blogtext strong {
	font-family: 'traveling';
	font-weight: bold;
	font-size: 24px;
}

.blogtext h1 {
	font-family: 'MOM';
	text-align:center;
	text-transform:uppercase;
	font-weight: normal;
	font-size: 40px;
	line-height: 52px;
}

.blogtext h2 {
	font-family: 'MOM';
	text-align:center;
	font-weight: normal;
	font-size: 30px;
	line-height: auto;
}

.blogtext h3 {
	font-family: 'sears';
	font-weight: normal;
	text-transform:uppercase;
	text-align:center;
	font-size: 25px;
	line-height: auto;
	text-transform: none;
	color: #000000;
}

.blogtext h4 {
	font-family: 'scratch';
	text-transform:uppercase;
	text-align:center;
	font-size: 30px;
	line-height: auto;
	color: #ff3c00;
}

.blogtext h5 {
	font-family: 'sears';
	text-transform: none;
	text-align:center;
	font-size: 18px;
	line-height: auto;
}

.blogtext h6 {
		font-family: 'sears';
		font-size: 28px;
    text-shadow: -1.2px -1.2px 0.2px #ffffff,
             -2.4px -2.4px 0.4px #b559d0,
             -3.6px -3.6px 0.6px #d27fdb,
             -4.8px -4.8px 0.8px #7e5cc9,
             -6px -6px 1px #cd7dd3,
             -7.2px -7.2px 1.2px #9b63d4,
             -8.4px -8.4px 1.4px #9577d5,
             -9.6px -9.6px 1.6px #c164ca,
             -10.8px -10.8px 1.8px #bb7dd1,
             -12px -12px 2px #a155c4;
	text-align:center;
}

.blogtext img {
	padding: .2rem;
}

.blogtext a {
	color: #000000;
	font-weight: bold;
	text-decoration: underline;
}

.blogtext a:visited {
	color: #808080;
}

/* =Rack Frame
   ------------------------------------------------------------
   The "rack mount" display frame system — the repeated cap/paper/
   content stack used throughout catsingle.php and elsewhere. The old
   version spread the same idea across many separately-tuned classes
   (#topper, .fullwrap, .rackmountlabel, #botter, plus the *wide
   variants .fullwrapwide, .blogwrapwide, .rackmountwideimg,
   .rackmountwideblog, .rackmountwidetext, and the related
   .musicshelf/#vidbox), each hand-padding its own box to line up
   with a background image, often by splitting one inset across a
   parent's padding-left AND a child's padding-left (e.g.
   .fullwrap's 217px + .rackmountlabel's old 6px = 223px) — fragile,
   since changing either number on its own silently breaks alignment,
   and it's how several real bugs slipped in (gaps between content
   and the printed label artwork, a cropped rainbow cap from a stray
   negative margin).

   Convention here: one inset, expressed once, as margin-left, on
   the single element that holds real content — never padding,
   never split across nesting levels. Box width is always set to
   match the artwork's printed area exactly (measured by sampling
   the PNG, not eyeballed).

   Converted, all using .rack-cap/.rack-paper/.rack-content below:
   the `music`/`photos`/`vidlings`, `vault`/`episodes`, and
   `zines`/`hoofsip` branches of catsingle.php; the standalone
   `narrow-text.php` page template (used by exactly one live page,
   /updates — confirmed via a wp_postmeta query, not assumed dead
   just because it's an unusual setup: most of this site is posts,
   not pages, so a page template is rare but real); and the wide
   family (`flyers`/`gifs` and `blog`/`merch` branches of
   catsingle.php, plus text.php's six pages: CONTACT, 20 YEARS OF
   MADNESS, PHOTOS, No Access, 20YOM Pics, ARTWORK — confirmed via
   wp_postmeta). vault/episodes also adds .rack-screen for its
   video-excerpt block, replacing #vidbox/.vidscreen.

   Deleted, confirmed dead by a theme-wide grep (not just
   catsingle.php — narrow-text.php also referenced
   .rackmountcredits): #topper, .fullwrap, #botter,
   .rackmountcredits, .rackmountzines, #vidbox, .vidscreen,
   #topperwide, #botterwide, .fullwrapwide, .blogwrapwide,
   .rackmountwideimg, .rackmountwideblog, .rackmountwidetext.

   Two long-standing alignment quirks were fixed (not preserved) in
   the wide-family conversion:
   - the old paper sheet sat at margin-left 12px while the caps sat
     at 13px, so the paper poked 1px past the cap on the left and
     fell 1px short on the right. Everything between the caps
     (paper + content together) now sits 1px further right, centered
     exactly like the caps — content stays exactly on the printed
     area of the artwork, because they moved together.
   - .blogwrapwide had a stray `padding: 2px` meant for vertical
     breathing room (the site-wide border-box sizing kept it from
     changing the box's outer width; its content wrapper compensated
     for the 2px left inset with margin-left 11 instead of 13). The
     2px vertical rhythm is preserved on .rack-content--blog below;
     the compensation dance is gone.

   Audited and left unconverted, on purpose:
   - pics.php (.picswrapwide/.picswideimg) and artifacto.php
     (.artifactowrap) don't use the cap/paper artwork stack (pics is
     a fixed-height gallery box, artifacto is a plain black
     Flash-player box). artifacto's INNER wrapper, though, was
     .rackmountwideimg — it now uses .rack-content--img like the
     flyers/gifs pages (the geometry rule below is scoped to both
     .rack-paper--wide and .artifactowrap for exactly this reason).
     .artifactowrap itself keeps its old 12px margin on purpose:
     there's no cap artwork on that page to align with.
   - loop-customcat.php's `music` archive listing (.musicshelf) has
     no split-inset bug — its wrapper already sits at the correct
     13px (aligned with the caps' centered position).
   - pics.php (.picswrapwide/.picswideimg) is a fixed-height box
     (1100x690 / 1080x575) sized around the go_portfolio gallery
     embed on /gallery, with a -12px bottom margin pulling the
     footer up. Kludgey, but it has no artwork to misalign against;
     reworking it now risks the gallery layout for zero
     visitor-visible benefit. TEMPORARY: left as-is until the
     go_portfolio replacement project (see the to-do doc) makes this
     template's future clear — still an open item.

   Only delete an old selector once every template/branch that
   referenced it has been converted — several of these are shared
   across multiple templates, so one branch moving to the new markup
   does not make the old CSS rule dead yet. Before deleting anything,
   grep the WHOLE theme directory, not just catsingle.php. */

.rack-cap--narrow {
	width: 1074px;
	margin: 0 auto;
}
.rack-cap--top.rack-cap--narrow {
	background-image: url(/assets/images/structure/fullrack-topper.png);
	background-repeat: no-repeat;
	height: 29px;
}
.rack-cap--bottom.rack-cap--narrow {
	background-image: url(/assets/images/structure/fullrack-bottom.png);
	background-repeat: no-repeat;
	height: 46px;
}

.rack-paper--narrow {
	background-image: url(/assets/images/structure/fullrack-label.png);
	background-repeat: repeat-y;
	width: 1074px;
	margin: 0 auto;
}

/* The one rule that matters: position via margin, width matched
   exactly to the printed label area measured off the artwork
   (fullrack-label.png: cream zone runs x=223 to x=848, 626px wide). */
.rack-paper--narrow .rack-content {
	width: 626px;
	margin-left: 223px;
	text-align: center;
}

/* .rack-content--credits — used by the `vault`/`episodes` branch.
   That content starts/ends with headings (h3/h4), not <p> tags, so
   it can't rely on .rack-content p's per-paragraph padding below
   for top/bottom breathing room the way the music branch's
   p-wrapped embed can. Matches the old .rackmountcredits container
   padding exactly. */
.rack-content--credits {
	padding-top: 15px;
	padding-bottom: 15px;
}

/* Defensive: the_content() here can include an <img> missing its size-* class, same overflow risk already fixed twice elsewhere in this project. */
.rack-content--credits img {
	max-width: 100%;
	height: auto;
}

/* .rack-content--zines — used by the `zines`/`hoofsip` branch.
   Content always leads with a zine-cover image (no top padding
   wanted — already handled by the p:first-child:has(img) rule
   above) but ends with a non-<p> related-issues block, so it still
   needs its own bottom breathing room. Matches the old
   .rackmountzines container padding-bottom exactly. */
.rack-content--zines {
	padding-bottom: 15px;
}

.rack-content p {
	padding: 0.55em 0;
	margin: 0 0 1.5em;
}

/* A leading media embed never needs the paragraph breathing room
   that real body-text paragraphs need above/below them. Scoped to
   "paragraph that contains a media embed" rather than just
   ":first-child" — vault/episodes posts start .rack-content with a
   genuine title/credits paragraph, which still needs its padding.
   The --text family is excluded: text.php's pages (contact etc.)
   have always rendered their leading image WITH the paragraph
   padding above it, and stripping it would raise everything on
   those pages by ~11px. */
.rack-content:not(.rack-content--text) > p:first-child:has(iframe),
.rack-content:not(.rack-content--text) > p:first-child:has(img) {
	padding-top: 0;
}

/* ---- The WIDE variant ----
   Same anatomy as the narrow system above, using the wider artwork
   set. Used by catsingle.php's `flyers`/`gifs` and `blog`/`merch`
   branches and by text.php (six pages: CONTACT, 20 YEARS OF
   MADNESS, PHOTOS, No Access, 20YOM Pics, ARTWORK). */

.rack-cap--wide {
	width: 1074px;
	margin: 0 auto;
}
.rack-cap--top.rack-cap--wide {
	background-image: url(/assets/images/structure/fullrack-topperwide.png);
	background-repeat: no-repeat;
	height: 49px;
}
.rack-cap--bottom.rack-cap--wide {
	background-image: url(/assets/images/structure/fullrack-bottomwide.png);
	background-repeat: no-repeat;
	height: 77px;
}

.rack-paper--wide {
	background-image: url(/assets/images/structure/fullrack-paperwide.png);
	background-repeat: repeat-y;
	width: 1074px;
	margin: 0 auto;
	/* text-align lives on the PAPER here (not just .rack-content, which
	   re-declares it anyway) on purpose: some older posts' pasted
	   content contains an unbalanced </div> that closes .rack-content
	   early, spilling the rest of the post directly into this element.
	   The old .fullwrapwide/.blogwrapwide centered that spilled content;
	   dropping this would left-align it (found the hard way on
	   /blog/20-years-of-madness's streaming-button row). */
	text-align: center;
}

/* Same "one inset, expressed once" rule as the narrow system:
   width matched exactly to the printed paper area measured off the
   artwork (fullrack-paperwide.png: cream zone runs x=13 to x=1057,
   1045px wide). Also scoped to .artifactowrap — artifacto.php's
   inner content wrapper shares this geometry without using the
   cap/paper artwork (see the roadmap comment above). */
.rack-paper--wide .rack-content,
.artifactowrap .rack-content {
	width: 1045px;
	margin-left: 13px;
	text-align: center;
}

/* .rack-content--text — used by text.php. Its paragraphs get the
   standard .rack-content p prose rhythm above; the wrapper itself
   needs the same bottom breathing room as the zines variant, PLUS
   a narrower content box: the old .rackmountwidetext declared
   width:1045 with padding-left:13, and under the site-wide
   border-box sizing that shoved the padding INSIDE the width,
   leaving a 1032px text column. Kept at 1032px on purpose — the
   six text.php pages' line wrapping depends on it, so "correcting"
   it to the full 1045px printed area would re-flow their text. */
.rack-content--zines,
.rack-content--text {
	padding-bottom: 15px;
}

.rack-paper--wide .rack-content--text {
	width: 1032px;
}

/* .rack-content--img — used by the `flyers`/`gifs` branch of
   catsingle.php and by artifacto.php's player box. This content is
   full-bleed artwork scans, not prose: every image is forced to the
   full printed-area width, and paragraphs get NO prose rhythm (the
   old .rackmountwideimg had no paragraph styling at all — adding
   the .rack-content p padding here would push the images around). */
.rack-content--img p {
	padding: 0;
	margin: 0;
}

.rack-content--img img {
	width: 1045px;
	display: block;
}

/* WordPress's base img.aligncenter/left/right rules (see =WP Images
   further up) add a 5px bottom margin — full-bleed scans stack edge
   to edge, so that margin is zeroed here. Same override the old
   .rackmountwideimg/.rackmountwideblog carried. */
.rack-content--img img.aligncenter,
.rack-content--img img.alignleft,
.rack-content--img img.alignright,
.rack-content--blog img.aligncenter,
.rack-content--blog img.alignleft,
.rack-content--blog img.alignright {
	margin-bottom: 0;
}

/* .rack-content--blog — used by the `blog`/`merch` branch of
   catsingle.php. The 2px top/bottom padding preserves the vertical
   rhythm the old .blogwrapwide got from its accidental
   `padding: 2px` (see the alignment-fix note in the roadmap comment
   above). Blog paragraphs use the 'traveling' typewriter face with
   a fixed 32px rhythm instead of the standard .rack-content p
   prose padding — this rule sits after .rack-content p in the file
   specifically so it wins that cascade tie. */
.rack-content--blog {
	padding-top: 2px;
	padding-bottom: 2px;
}

/* Unscoped (not .mobile-shell-only) — like .rack-content--credits img
   further up, this applies at every width including desktop, since a
   live-content survey found many real /blog posts' floated images
   (alignleft/alignright) carry no size-* class at all, relying only
   on inline width/height attributes up to ~1045px native — some
   already overflow the fixed 1045px desktop column today, not just a
   fluid one. A per-post content fix (the approach used for vault/
   episodes/music's much smaller image counts) doesn't scale here —
   the same survey found 263 such images across 27 posts — so this is
   a deliberate scoped-CSS deviation from that "fix data, not CSS"
   precedent, justified purely by scale. */
.rack-content--blog img {
	max-width: 100%;
	height: auto;
}

.rack-content--blog p {
	font-family: 'traveling';
	display: block;
	padding: 0 0 32px;
	line-height: 32px;
}

/* =Gallery Masonry
   .rack-content--gallery / .masonry-item — the category-archive
   counterpart to .rack-content--img: used by category.php's
   rack-frame-wrapped archive view (currently just `artwork`, the
   go_portfolio-replacement test case — see the 30MOMeval
   gallery-restructure docs). Still gets the shared
   `.rack-paper--wide .rack-content` width/margin-left from the rule
   above; text-align:center from that same rule is harmless here
   (doesn't affect a column layout).

   Deliberately NOT a fixed-box grid like .boxpreview/.gifpreview:
   those exist because flyers/gifs scans are consistently shaped.
   Artwork images vary wildly (portrait, landscape, square), so
   forcing them into identical boxes would mean heavy letterboxing or
   cropping. CSS multi-column masonry instead: fixed column count,
   each image keeps its own natural aspect ratio, items just pack
   into whichever column has room next. No JS masonry library needed,
   and — unlike go_portfolio's admin-ajax-dependent version — this
   survives static flattening since it's pure CSS.

   column-count's `4` is now a fallback only, not hardcoded —
   overridable per call via [wahnsinn_gallery]'s `cols` attribute
   (functions.php section 16), which sets --wahnsinn-gallery-cols
   inline. The /artwork category archive's own hardcoded markup never
   sets that property, so it (and every pre-existing shortcode call)
   keeps resolving to this same `4` regardless. Desktop-only on
   purpose — the tablet/mobile column counts below are their own
   separate, more specific, still-hardcoded rules that win outright
   regardless of this value. */
.rack-content--gallery {
	column-count: var(--wahnsinn-gallery-cols, 4);
	column-gap: 13px;
	padding: 13px 0;
}

/* .masonry-item is a <figure> element — margin:0 cancels the
   browser's default figure margin (1em 40px); margin-bottom:13px
   still wins for that one side since it's declared after (same rule,
   later declaration for the same longhand overrides the shorthand).
   Left/right must land at exactly 0 here — this sits inside a CSS
   multi-column layout (.rack-content--gallery, column-count:4), where
   any nonzero side margin would throw off column width. */
.masonry-item {
	margin: 0 0 13px 0;
	break-inside: avoid;
}

.masonry-item a {
	display: block;
}

.masonry-item img {
	width: 100%;
	display: block;
	transition: filter 0.15s ease-in-out;
}

/* Hover hint that these images are clickable (same filter:brightness()
   technique the nav buttons' facebreathe animation uses elsewhere in
   this file, just triggered by :hover instead of looping). Scoped to
   (hover: hover) and (pointer: fine) — real mouse input only — so
   touch devices don't get a "stuck" brightened image after a tap. */
@media (hover: hover) and (pointer: fine) {
	.masonry-item a:hover img {
		filter: brightness(1.08);
	}
}

/* =Gallery Lightbox permalink button
   .gallery-permalink-btn — a single shared element, created once by
   gallery-lightbox-init.js and appended directly into GLightbox's own
   .gcontainer (the same fixed, full-viewport element .gnext/.gprev/
   .gclose anchor to — see glightbox.css), not into any per-slide
   description area. A per-slide description shrink-wraps to that
   slide's own image height, so it can never hold a consistent screen
   position independent of the image's aspect ratio; anchoring to
   .gcontainer instead means this button sits at the same fixed spot
   near the bottom of the viewport on every slide — overlapping a
   portrait/square image that fills that space, and floating in the
   empty area below a landscape image that doesn't. Styled to echo
   the built-in nav arrows (circle instead of their rounded rectangle,
   slightly larger; background/hover match the arrows' own desktop
   values exactly — `.glightbox-clean .gprev/.gnext/.gclose` inside
   glightbox.css's `@media (min-width: 769px)` block — not their
   <769px default, which is a different, more opaque value). Icon
   rotated 90deg since Genericons' link glyph draws vertically by
   default. Below GLightbox's own 768px mobile breakpoint the built-in
   nav arrows are effectively swipe-only at that point, so this button
   drops to 50% opacity there too rather than compete for attention.
   `bottom: 24px` deliberately matches the arrows' own
   `left: 30px` / `right: 30px` side margin (glightbox.css's
   `.glightbox-clean .gprev/.gnext` — fixed px, unchanged across every
   breakpoint, confirmed by reading the source), nudged a further 6px
   closer to the edge since a circle's visual weight sits differently
   than the arrows' rectangles. Matches the arrows' actual fixed value
   directly rather than an earlier vh-based proportional guess. Live
   on Artwork, Photos, and doc — see loop-customcat.php / functions.php
   section 15. */
.gallery-permalink-btn {
	position: absolute;
	z-index: 99999;
	bottom: 24px;
	left: 50%;
	transform: translateX(-50%);
	width: 52px;
	height: 52px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background-color: rgba(0, 0, 0, 0.32);
	cursor: pointer;
}

/* Genericons' link glyph draws as a vertical chain link by default;
   rotated flat to read correctly at a glance. */
.gallery-permalink-btn .genericon-link {
	font-size: 28px;
	color: #fff;
	transform: rotate(90deg);
}

.gallery-permalink-btn:hover {
	background-color: rgba(0, 0, 0, 0.7);
}

/* GLightbox's own prev/next/close controls are effectively unusable
   below its own mobile breakpoint (768px) — swipe takes over instead.
   The permalink button still works via tap, so it stays, just
   quieted down to half-opacity to match how secondary the nav
   controls become at this size. */
@media (max-width: 768px) {
	.gallery-permalink-btn {
		opacity: 0.5;
	}
}

/* =Gallery Carousel
   .wahnsinn-carousel — the [wahnsinn_carousel] shortcode's own inline
   Splide carousel (functions.php section 17), for a one-off image set
   embedded in a single post's content rather than a full gallery
   category archive (see .rack-content--gallery/.masonry-item above for
   that pattern). First used on the "30MOM Black on Red T-shirt" merch
   post replacing go_portfolio's "slider" layout-type. Sits inside
   .blogtext/.rack-content--blog's 1045px column, so no width rule is
   needed here — Splide's own .splide__track already fills its
   container. Arrow/pagination colors echo the grey-circle language
   .gallery-permalink-btn already established for lightbox controls
   elsewhere on the site, rather than introducing a new visual style
   just for this one carousel. */
.wahnsinn-carousel {
	margin: 20px 0;
}

.wahnsinn-carousel .splide__slide img {
	width: 100%;
	display: block;
	transition: filter 0.15s ease-in-out;
}

@media (hover: hover) and (pointer: fine) {
	.wahnsinn-carousel .splide__slide a:hover img {
		filter: brightness(1.08);
	}
}

.wahnsinn-carousel .splide__arrow {
	background: rgba(0, 0, 0, 0.32);
	opacity: 1;
}

.wahnsinn-carousel .splide__arrow svg {
	fill: #fff;
}

.wahnsinn-carousel .splide__arrow:hover:not(:disabled) {
	background: rgba(0, 0, 0, 0.7);
}

.wahnsinn-carousel .splide__pagination__page {
	background: rgba(0, 0, 0, 0.32);
}

.wahnsinn-carousel .splide__pagination__page.is-active {
	background: rgba(0, 0, 0, 0.7);
}

/* =Gallery Grid
   .wahnsinn-grid — the [wahnsinn_grid] shortcode's static CSS grid
   (functions.php section 18), for a one-off fixed-order image set
   embedded in a single post (first used for the HOOFSIP 1-36 cover
   grid on the "Hoofsip Subscriptions" merch post, replacing
   go_portfolio's "grid" layout-type). No JS layout library — plain
   CSS grid, --wahnsinn-grid-cols set inline per shortcode call
   (defaults to 6, matching this gallery's original column-layout).
   4px gap (go_portfolio's own 5px h-space/v-space looked tighter than
   this grid's first pass at that value — root cause turned out to be
   .blogtext img's sitewide `padding:
   .2rem` (below) leaking onto these images too, adding 3.2px on
   every side INSIDE each border-box image and stacking with the grid
   gap for an effective ~11px gap instead of 5px; reset to 0 below).
   aspect-ratio 17/22 approximates the covers' real ~8.5x11" scan
   proportions (measured ~1274x1649px) so slightly-inconsistent scan
   crops still sit in a uniform grid; object-fit:cover crops the
   small overflow rather than letterboxing or stretching. This is now
   the DEFAULT only, not a hardcoded value — overridable per shortcode
   call via [wahnsinn_grid]'s `aspect_ratio` attribute (functions.php
   section 18), which sets --wahnsinn-grid-aspect-ratio inline; the
   `, 17 / 22` fallback below is what every pre-existing call (which
   never set that attribute) keeps rendering off. */
.wahnsinn-grid {
	display: grid;
	grid-template-columns: repeat(var(--wahnsinn-grid-cols, 6), 1fr);
	gap: 4px;
}

.wahnsinn-grid a {
	position: relative;
	display: block;
}

.wahnsinn-grid img {
	width: 100%;
	display: block;
	aspect-ratio: var(--wahnsinn-grid-aspect-ratio, 17 / 22);
	object-fit: cover;
	padding: 0;
}

/* Hover-dim, values matched directly to go_portfolio's own CSS for
   this exact gallery rather than approximated: overlay-color #333333
   and overlay-opacity 15 (this gallery's inline
   .gw-gopf-post-overlay-bg background-color/opacity), fading in via
   the same `transition: opacity 0.3s ease-in-out` go_portfolio_
   styles.css uses on .gw-gopf-post-overlay-hover:hover .gw-gopf-post-
   overlay. */
.wahnsinn-grid a::after {
	content: "";
	position: absolute;
	inset: 0;
	background: #333333;
	opacity: 0;
	transition: opacity 0.3s ease-in-out;
}

.wahnsinn-grid a:hover::after {
	opacity: 0.15;
}

/* =Hoofsip Grid
   .wahnsinn-hoofsip-grid — the [wahnsinn_hoofsip_grid] shortcode's
   static post-card grid (functions.php section 21), replacing
   go_portfolio's "HOOFSIP" gallery on the HOOFSIP hub post and every
   individual issue post that embeds it. Unlike .wahnsinn-grid (above)
   this is a grid of real WordPress posts, not attachments, so each
   card carries a title + summary under the cover, not just an image.

   Cover images reuse .wahnsinn-grid's exact aspect-ratio/object-fit
   treatment (17/22, cover) for the same reason: these are the same
   HOOFSIP cover scans, already confirmed close enough to uniform that
   cropping the small overflow reads better than letterboxing.

   Gap (10px) and hover-dim (#333333 at 30% opacity) were measured
   directly off go_portfolio's own live rendering of this exact gallery
   and matched, not approximated — h-space/v-space and overlay-
   color/overlay-opacity in its own config. The hover-dim reuses
   .wahnsinn-grid's ::after technique above rather than go_portfolio's
   fancier slide-reveal animation (same visual result, simpler), scoped
   to .wahnsinn-hoofsip-grid-cover itself so only hovering the actual
   image dims it — hovering the title or summary does nothing to it.

   The card background reuses the same tiled paper texture as #zinebg
   (see that rule below, "used directly in post content" — this is the
   same /assets/images/structure/paper-tiled.gif image, just applied via a class instead
   of that specific id, since a background-image can be shared across
   any number of selectors without needing to share the element itself).
   Title size/color/hover and the summary's spacing are deliberate
   choices, not a go_portfolio match.

   .wahnsinn-hoofsip-grid-summary is the one element given a genuinely
   fixed height (the cover is only *consistent*, via aspect-ratio, not
   fixed to a literal px value) — text comes straight from each post's
   real post_excerpt now (get_the_excerpt(), functions.php section 21),
   pre-written to fit this exact box rather than trimmed at render time
   (an earlier version regex-extracted a summary from post_content and
   trimmed it client-side against the live box; once that settled on
   good text it was copied into post_excerpt for real and both of those
   were deleted — see functions.php section 21's comment). overflow:
   hidden here is just a safety net in case a future excerpt is written
   longer than this box actually holds. */
.wahnsinn-hoofsip-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 10px;
}

.wahnsinn-hoofsip-grid-item {
	display: flex;
	flex-direction: column;
	background: url('/assets/images/structure/paper-tiled.gif') 0px 0;
}

.wahnsinn-hoofsip-grid-cover {
	position: relative;
	display: block;
	overflow: hidden;
}

.wahnsinn-hoofsip-grid-cover img {
	width: 100%;
	display: block;
	aspect-ratio: 17 / 22;
	object-fit: cover;
}

.wahnsinn-hoofsip-grid-cover::after {
	content: "";
	position: absolute;
	inset: 0;
	background: #333333;
	opacity: 0;
	transition: opacity 0.3s ease-in-out;
}

.wahnsinn-hoofsip-grid-cover:hover::after {
	opacity: 0.3;
}

.wahnsinn-hoofsip-grid-title {
	display: block;
	font-size: 14px;
	line-height: 16px; /* the ambient inherited line-height here is ~29px for a 14px font — nearly all the visible space above/below this single line was that, not padding */
	color: #000000;
	text-align: center;
	padding: 3px 6px;
}

.wahnsinn-hoofsip-grid-title:visited {
	color: #000000;
}

.wahnsinn-hoofsip-grid-title:hover {
	color: #E00000;
}

.wahnsinn-hoofsip-grid-summary {
	display: block;
	overflow: hidden;
	height: 84px; /* 80px text area (5 lines at 16px line-height) + 4px bottom padding — this theme is sitewide box-sizing:border-box, so height has to include padding or it eats into the text area */
	font-size: 12px;
	line-height: 16px;
	color: #000000;
	text-align: center;
	padding: 0 6px 4px;
}

/* .rack-screen — used by the `vault`/`episodes` branch of
   catsingle.php for the excerpt-field video embed, which renders
   before the cap/paper/content stack above. Replaces #vidbox/
   .vidscreen. */
.rack-screen {
	background-image: url(/assets/images/structure/fullrack.png);
	background-repeat: repeat-y;
	width: 1074px;
	margin: 0 auto;
}

/* Position via margin, width matched to the dark screen area
   measured directly off the artwork (fullrack.png: dark zone runs
   x=215 to x=859, 645px wide). */
.rack-screen__inner {
	width: 645px;
	margin-left: 215px;
	text-align: center;
}

/* Most vault/episodes posts' excerpt field is a raw, unstyled embed —
   112 of 124 are a Vimeo <iframe width="640" height="480">, 11 more
   are a plain <video width="640" height="...">, neither carrying any
   class. <video> (like <img>) gets its width/height HTML attributes
   mapped to an intrinsic aspect-ratio by the browser, so width:100%/
   height:auto is enough to make it track the container both ways —
   no CSS aspect-ratio property needed (this project hit real
   cross-browser aspect-ratio rounding bugs elsewhere and standardized
   on other techniques instead, see .preview/.vhssm).

   width:100%, not max-width:100% — max-width only lets the video
   shrink below its intrinsic 640px, never grow past it, so on a
   mobile-shell viewport wider than 640px (.rack-screen__inner is
   fluid up to 767px, see the mobile block below) the video stalled
   at 640px, centered, with visible black letterboxing on both sides
   (video's own default background) instead of filling the width —
   confirmed and fixed after the owner caught it live.

   :not(.locura-video-player__video) excludes the one post (of 124)
   using the newer .locura-video-player component, which already sets
   its own height:100% inside an aspect-ratio wrapper — this selector
   is more specific than .locura-video-player__video alone and would
   otherwise win and clobber that height with auto. */
.rack-screen__inner video:not(.locura-video-player__video) {
	width: 100%;
	height: auto;
}

/* <iframe> does NOT get the same width/height-attribute-to-intrinsic-
   ratio treatment <video>/<img> do — confirmed by testing: an
   unstyled <iframe> with height:auto collapses to the browser's
   generic replaced-element default of 150px instead of preserving
   its real ratio, visibly squashing the Vimeo embed. Needs the
   height:0/padding-bottom wrapper technique instead (same one used
   for #footer's tablet fix elsewhere in this file), targeted at the
   containing <p> — wpautop always wraps a lone excerpt embed in one —
   reusing the exact :has(iframe) selector pattern already
   established just above for .rack-content's own padding fix.

   Not one universal ratio — a direct DB survey of every published
   vault/episodes post's real iframe width/height attributes found
   640x480 (4:3) for the large majority (100 posts), but also 640x360
   (16:9, 6 posts, e.g. /vault/feels-pretty-good) and 640x493 (4
   posts). 75% is the default (covers 480 plus the one post with no
   width/height attributes at all — ID 6900, inline
   style="width:640px;height:480px" instead, also 4:3, still falls
   through to this default correctly); the two attribute-selector
   overrides below catch the other two known ratios by their real
   HTML height attribute — no JS measurement needed. If a future post
   ever ships a still-different ratio, it'll silently fall back to
   this 75% default until a matching rule is added here. */
.rack-screen__inner p:has(iframe) {
	position: relative;
	height: 0;
	padding-bottom: 75%;
	overflow: hidden;
}

.rack-screen__inner p:has(iframe[height="360"]) {
	padding-bottom: 56.25%;
}

.rack-screen__inner p:has(iframe[height="493"]) {
	padding-bottom: 77.03125%;
}

.rack-screen__inner p:has(iframe) iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

/* .rack-content--credits video/iframe — a SECOND, separate embed some
   vault/episodes posts add further down in the actual post body (via
   the_content()), distinct from the one excerpt-field embed
   .rack-screen__inner handles above. Confirmed by a full DB survey of
   every published vault/episodes post's post_content: 8 <iframe>s
   across 7 posts (Episode One/Six/Fifteen, Intro 6, Suburban Legend
   x2, Dick Fishin', Chocolate Milk) plus one plain <video> (Episode
   Fourteen). Until now NEITHER had any responsive handling at all —
   .rack-screen__inner's own fix is deliberately scoped to just that
   one element, not .rack-content generally.

   Some of these iframes/the video are wrapped in <div class="invid">
   (a dead class — see the "invid — removed" comment near the top of
   this file; its old -3px positioning rule was deleted from some but
   not all posts that used it, so the wrapper itself is inconsistent
   and NOT something to key a selector off). Others (Suburban Legend's)
   have no wrapper div at all, just wpautop's own <p>. The selectors
   below cover both shapes directly rather than relying on any
   particular wrapper element or class. */
.rack-content--credits video {
	width: 100%;
	height: auto;
}

/* :has(> iframe) — NOT :has(iframe) — is deliberate on every div
   selector in this file (the p ones are safe either way: a <p> can't
   contain a nested <div>/<p>, so :has(iframe) on a <p> can only ever
   match a genuinely direct wrapper). :has(iframe) with no child
   combinator matches an iframe at ANY depth, not just a direct child —
   a real, confirmed bug: /blog/from-the-finger-2025-03-05 wraps its
   whole body in <div class="blogtext">, with its two iframes sitting
   several levels deeper inside <p> tags nested within it. Plain
   div:has(iframe) matched .blogtext itself (a div with an iframe
   *descendant*, not a direct child), collapsing the entire wrapper —
   and everything in it — down to a small height:0/padding-bottom box
   with overflow:hidden, hiding most of the post. :has(> iframe)
   restricts the match to a div whose iframe is a genuine direct
   child (the actual per-embed wrapper divs this rule is meant for,
   e.g. the vault/episodes "invid"-adjacent ones), leaving any larger
   ancestor div untouched. */
/* flex:1 1 0% is a real, owner-reported fix, not defensive — found on
   /blog/20-years-of-madness's "Bonus Vids & Deleted Scenes" section
   (a .rack-content--blog case, see that rule below), which wraps each
   pair of videos in an author-authored <div style="display:flex;
   gap:14px"> for a real two-column side-by-side layout, rather than
   the plain <p>/<div> block wrapping every other embed on the site
   uses. The height:0/padding-bottom% technique assumes its own box is
   a normal block box that fills its parent's width by default — a
   flex ITEM instead sizes itself from flex-basis/content, and since
   this rule already pulls the iframe out of flow via position:
   absolute (so it contributes zero intrinsic size), a flex item here
   had nothing left to size itself from and collapsed to 0x0, silently
   deleting the videos from view entirely (confirmed live: the wrapper
   div's own rect was 0x0, at every viewport width, not just mobile —
   this bug has nothing to do with the mobile-shell breakpoints at
   all). flex:1 1 0% gives it a real basis to grow from, splitting the
   flex row evenly with its sibling (matching the two videos' own
   authored 515px-each intent). Safe to add unconditionally: the flex
   shorthand is simply ignored on any element that isn't actually a
   flex item, so this has zero effect on the (vast majority) plain
   block-context uses of this same rule elsewhere. */
.rack-content--credits p:has(iframe),
.rack-content--credits div:has(> iframe) {
	position: relative;
	height: 0;
	padding-bottom: 75%;
	overflow: hidden;
	flex: 1 1 0%;
}

/* Real ratios found in the survey above: 627x353 and 627x470 — not
   arbitrary pixel pairs, they're Vimeo/YouTube's standard 16:9 and
   4:3 oEmbed sizes, each just rounded to the nearest whole-pixel
   height at 627px width (627 * 9/16 = 352.69 -> 353; 627 * 3/4 =
   470.25 -> 470). Written here as the exact ratios (56.25%/75%), not
   the rounded 56.3%/74.96% the raw pixels imply, so a future embed at
   a different width that still lands on one of these two standard
   ratios stays correct without new math — only the attribute-selector
   matches below (keyed to the actual height="" values seen today)
   would need a new entry if a genuinely different ratio ever shows up,
   same known/accepted tradeoff .rack-screen__inner's own version of
   this takes. 75% (4:3) is the default above, matching height="470";
   the override below catches the other known ratio, height="353"
   (16:9). */
.rack-content--credits p:has(iframe[height="353"]),
.rack-content--credits div:has(> iframe[height="353"]) {
	padding-bottom: 56.25%;
}

.rack-content--credits p:has(iframe) iframe,
.rack-content--credits div:has(> iframe) iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

/* .rack-content--blog video/iframe — same technique and reasoning as
   .rack-content--credits above, unscoped (applies at every width, not
   just mobile/tablet) since these embeds are fixed-px today regardless
   of viewport. A live-content survey of real /blog posts (curl'd
   rendered HTML, not raw DB content) found Vimeo/YouTube iframes at
   several distinct ratios plus one self-hosted <video>, and — same as
   above — both bare <p> and <div> wrappers depending on the post, so
   both selector shapes are covered directly. */
.rack-content--blog video {
	width: 100%;
	height: auto;
}

.rack-content--blog p:has(iframe),
.rack-content--blog div:has(> iframe) {
	position: relative;
	height: 0;
	padding-bottom: 75%; /* 640x480, the most common ratio found (the six "Top Ten" posts' 10-13 iframes each) */
	overflow: hidden;
	flex: 1 1 0%; /* see the .rack-content--credits version of this rule above for the full writeup — this exact rule is what needed it, on 20-years-of-madness's flex two-column "Bonus Vids" section */
}

.rack-content--blog p:has(iframe[height="360"]),
.rack-content--blog div:has(> iframe[height="360"]) {
	padding-bottom: 56.25%; /* 640x360, 16:9 */
}

.rack-content--blog p:has(iframe[height="588"]),
.rack-content--blog div:has(> iframe[height="588"]) {
	padding-bottom: 56.25%; /* 1045x588 — effectively 16:9 (588/1045=0.5626), written as the exact ratio rather than the rounded pixel one, same convention as .rack-content--credits' own version above */
}

.rack-content--blog p:has(iframe[height="501"]),
.rack-content--blog div:has(> iframe[height="501"]) {
	padding-bottom: 52.7368%; /* 950x501, from-the-finger-2025-03-05's second embed — not a standard 16:9/4:3 ratio, kept as its own exact match */
}

.rack-content--blog p:has(iframe[height="290"]),
.rack-content--blog div:has(> iframe[height="290"]) {
	padding-bottom: 56.3107%; /* 515x290 — 20-years-of-madness's secondary embeds */
}

/* A real, owner-reported bug the padding-bottom% rule above cannot
   actually fix for this specific embed: 20-years-of-madness's
   height="290" videos sit two-per-row in an author-authored
   <div style="display:flex; gap:14px">, and CSS padding percentages
   always resolve against the CONTAINING BLOCK's width (the flex ROW,
   ~1045px), never the flex ITEM's own actual width (~515.5px, half
   the row) — so 56.3107% of the row rendered roughly 2x too tall
   (confirmed live: 588px instead of ~290px) the instant the flex
   items were given a real size at all (see the flex:1 1 0% fix
   above, which fixed the 0x0 collapse but exposed this next). No
   percentage constant can fix this correctly at every viewport width
   (the flex item's share of the row isn't a fixed fraction of the
   row once you account for the fixed 14px gap), which is exactly the
   kind of case aspect-ratio is for, not padding-bottom — unlike this
   project's own documented reason for avoiding aspect-ratio elsewhere
   (a real cross-browser SUBPIXEL rounding gap between TWO adjacent
   sibling boxes that need to align edge-to-edge, .preview/.vhssm),
   there's no second box here that needs pixel-perfect alignment
   against this one, so that specific failure mode doesn't apply.
   Scoped narrowly via the flex-row parent selector so it only
   overrides the general rule above for this one shape, not the
   plain-<p>/<div>-wrapped majority of embeds that rule still
   correctly covers. */
.rack-content--blog div[style*="display: flex"] > div:has(> iframe[height="290"]) {
	height: auto;
	padding-bottom: 0;
	aspect-ratio: 515 / 290;
}

.rack-content--blog p:has(iframe) iframe,
.rack-content--blog div:has(> iframe) iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

/* One self-hosted <video> found (from-the-finger-2025-03-05) is
   portrait (660x1173) — the plain width:100%;height:auto rule above
   will render it as a tall block on mobile. This is the correct,
   natural consequence of proportional scaling for a portrait asset,
   not a bug, and deliberately gets no special-case height clamp —
   matching the goal of a category-wide fix with no per-post
   exceptions. Revisit only if it reads badly once live. */

/* This is the visibility half of the desktop/mobile nav swap — the
   appearance rules for #mobiletopmenu live up near the top of this
   file in the "Mobile Top Nav Menu" section; this is the other,
   intentional half. Hidden by default... */
#mobiletopmenu {
    display:none;
}

/* ...and swapped on below 1024px screen width: desktop #topmenu
   hides, #mobiletopmenu (styled up top) shows. This swap is based
   purely on CSS media-query width, not on a <meta name="viewport">
   tag — there isn't one on this site (confirmed intentional, the
   site owner relies on mobile browsers shrinking/zooming the whole
   desktop layout to fit). Worth knowing if you ever test this nav
   swap on a real phone and it behaves inconsistently across
   browsers: without a viewport tag, different mobile browsers can
   disagree about what "screen width" even means for this query. */
@media screen and (max-width: 1024px) {

    #topmenu {
        display:none !important;
    }

    #mobiletopmenu {
        display:block !important;
    }

    /* This block used to also force-zero margin-top on
     * #leftmenu, .one-column #content, .full-page #content, and
     * .single-30mom #content — undoing four separate hand-tuned
     * margin-top:61px values that existed only to compensate for
     * #topmenu being position:absolute on desktop. Now that #topmenu
     * (and #mobiletopmenu, hence the removed position:static
     * !important above) are both real document flow at every width,
     * nothing needs correcting here at all. */
}

/****************************
    /vault Mobile Layout (Phase 1 of a page-by-page mobile rollout)

    Everything below EXCEPT the .vault3/.preview/.vhssm archive-grid
    rules (near the bottom of this block) is scoped with a leading
    .mobile-shell instead of .category-vault — 'mobile-shell' is a
    body class wahnsinn_add_mobile_shell_body_class() (functions.php,
    section 26) adds on any category that gets this shared mobile
    header/hamburger/nav-bar treatment, currently /vault, /blog,
    /episodes, /music, /merch, and the /gallery landing page. This lives here in the shared style.css rather than a
    separate conditionally-loaded file, so .mobile-shell is the ONLY
    thing keeping these rules from reaching any other page — every
    shared rule in this section must keep that prefix. The archive-grid
    rules are the one part of this block that ISN'T shared (/blog and
    /episodes each use their own grid markup — .micro/.cart and
    .epcon/.vhsl respectively, restyled separately in their own
    sections right after this one) — those stay
    .category-vault-scoped, vault only.

    Two unconditional (no media query) rules come first — #hedmobile
    and #vaultNavToggle both default to hidden here, OUTSIDE the
    767px query below, so they stay off at every width above it. This
    matters: if these lived only inside the media query, both would
    render with no display rule at all above 767px (an unstyled
    <header> and <button> just sitting in the page), which is exactly
    the "duplicate header" bug this fixes.

    Everything else lives inside the single @media (max-width: 767px)
    block, INCLUDING the container-width overrides, on purpose:
    #wrapper/#content/#footer must stay genuinely fixed at 1100px
    (identical to every other page on the site) at every width ABOVE
    767px, so the .vault3 3-column float grid never gets a chance to
    wrap into a broken partial row — a fluid-but-still->1-column
    container width was tried first and rejected, since it let the
    grid wrap to 2 columns anywhere below ~1088px, which has no
    design to support it. The container width and the grid's column
    count now only ever change at the same instant, right here at
    767px. (/blog's own .micro/.cart grid, added later, follows the
    identical container-width/breakpoint logic — see the /blog Mobile
    Layout section below.)

    Known accepted tradeoff: real tablet-width visits (e.g. an iPad
    Air at 768px CSS width) will horizontally scroll the fixed
    1100px layout rather than shrink-to-fit like the rest of the site
    does today, since /vault and /blog now carry a real viewport meta
    tag (see header.php) and nothing below 767px changes that.
    Flagged for the site owner — the 3-column (or, for /blog,
    2-column) integrity requirement takes priority per their call; a
    JS dynamic-viewport technique could fully restore today's
    shrink-to-fit look above 767px later if the tablet scrolling
    turns out to bother them in practice. /vault got a real Phase 2
    fluid tablet layout instead (see /vault Tablet Layout below);
    /blog hasn't, so this tradeoff is still live there.
**********************************************/

.mobile-shell #hedmobile {
	display: none;
}

.mobile-shell #vaultNavToggle {
	display: none;
}

@media (max-width: 767px) {

	.mobile-shell #wrapper {
		width: 100%;
		background-image: none;
	}

	.mobile-shell .single-30mom #content {
		width: 100%;
	}

	/* Single vault posts' rack-frame content (video → credits paper →
	   prev/next tray), catsingle.php's vault/episodes branch. The
	   desktop art (fullrack.png etc.) is a fixed 1074px frame with a
	   ~40% decorative beige border on each side of the actual content
	   zone — scaling that fluidly would still burn a big chunk of a
	   narrow phone screen on empty border. Owner made dedicated mobile
	   assets instead (mobile-rack-topper/label/bottom.png, mobile-
	   tray.gif), each natively 644px wide — measured directly (same
	   convention as the rest of this file): only a 1-2px edge outline,
	   no large margin to preserve, so these go full-bleed with no inset
	   at all, unlike their desktop counterparts. Mobile-only by design
	   (confirmed with owner) — the 768-1024px tablet range intentionally
	   keeps the old fixed desktop rack chrome for now (only the nav/
	   header get tablet treatment), so none of this repeats in the
	   tablet media query below. */

	.mobile-shell .rack-screen {
		background-image: none;
		width: 100%;
		margin: 0 auto;
	}

	.mobile-shell .rack-screen__inner {
		width: 100%;
		margin-left: 0;
	}

	.mobile-shell .rack-cap--narrow,
	.mobile-shell .rack-cap--wide {
		width: 100%;
		margin: 0 auto;
	}

	/* No-repeat single caps (not tiled, so their own box height must
	   track width to avoid the background stretching/clipping out of
	   sync with a fluid box) — same height:0/padding-bottom technique
	   already used for #footer's tablet fix, not the CSS aspect-ratio
	   property (this project standardized on padding-bottom after
	   hitting real cross-browser aspect-ratio rounding bugs elsewhere).
	   29/628 and 46/628 — mobile-rack-topper.png/mobile-rack-bottom.png's
	   own measured native dimensions (re-measured after the owner
	   trimmed their width from 644px to 628px; heights unchanged).

	   --wide selectors added alongside --narrow here (not a separate
	   rule) when /blog singles joined: at this breakpoint BOTH rack
	   families collapse to the same 100%-width single column, so /blog
	   (which uses --wide, catsingle.php's blog/merch branch) reuses
	   these exact assets/percentages rather than getting its own
	   "mobile-rack-*-wide" art — confirmed with the owner, since the
	   wide/narrow distinction (a decorative-margin difference that
	   matters at desktop/tablet) has no meaning once the column is
	   already edge-to-edge. See "/blog Tablet Layout" further down for
	   where /blog's own art/percentages DO diverge (tablet keeps each
	   family's own desktop art, just made fluid). */
	.mobile-shell .rack-cap--top.rack-cap--narrow,
	.mobile-shell .rack-cap--top.rack-cap--wide {
		background-image: url(/assets/images/structure/mobile-rack-topper.png);
		background-size: 100% 100%;
		height: 0;
		padding-bottom: 4.6178%;
	}

	.mobile-shell .rack-cap--bottom.rack-cap--narrow,
	.mobile-shell .rack-cap--bottom.rack-cap--wide {
		background-image: url(/assets/images/structure/mobile-rack-bottom.png);
		background-size: 100% 100%;
		height: 0;
		padding-bottom: 7.3248%;
	}

	/* Paper texture repeats vertically to fit variable-length credits
	   text, unlike the single-instance caps above — background-size:
	   100% auto scales the tile's width to the fluid box while auto-
	   preserving the image's own aspect ratio for its height, same
	   technique already used for #hed/#hedsingle's own fluid scaling,
	   then repeat-y tiles that (uniformly scaled, undistorted) tile
	   down the box. --wide added alongside --narrow, same reasoning as
	   the caps above. */
	.mobile-shell .rack-paper--narrow,
	.mobile-shell .rack-paper--wide {
		background-image: url(/assets/images/structure/mobile-rack-label.png);
		background-repeat: repeat-y;
		background-size: 100% auto;
		width: 100%;
		margin: 0 auto;
	}

	.mobile-shell .rack-paper--narrow .rack-content,
	.mobile-shell .rack-paper--wide .rack-content {
		width: 100%;
		margin-left: 0;
	}

	/* .blogtext (defined near the top of this file, ~line 3330) is an
	   author-inserted "zine-style" typography wrapper some /blog posts
	   use, not template-guaranteed — width:90% is already fluid-safe,
	   but its margin-left:35px is a fixed px value that overflows a
	   narrow, fluid .rack-content--blog column (a 90%-wide box plus a
	   fixed 35px left margin no longer fits inside its own parent once
	   that parent shrinks below ~350px). Converted to the same
	   px÷native-reference-width percentage this project uses
	   everywhere: 35/1045 (the desktop .rack-content column's own
	   native width). Posts that don't use .blogtext are unaffected —
	   the selector simply won't match. */
	.mobile-shell .rack-content--blog .blogtext {
		margin-left: 3.3493%;
	}

	/* .rack-content--img (single /photos posts, catsingle.php's flyers/
	   gifs/artwork/photos/doc branch — see style.css ~3683 for the
	   unscoped desktop rule) hardcodes width:1045px on its own <img>,
	   matching the desktop .rack-content column's own fixed width
	   exactly — this is the one genuinely new CSS fix the /photos join
	   needed for singles, everything else (.rack-cap--wide/
	   .rack-paper--wide chrome, #fulltray) was already generic from the
	   /blog Singles join. Deliberately .mobile-shell-scoped rather than
	   an unscoped max-width like .rack-content--credits/--blog's own
	   img rules — this same class is also used by artifacto.php's
	   player box (a separate, already-deployed project, not part of
	   this mobile-shell mechanism at all), so an unscoped change here
	   would reach a page this join has no business touching. */
	.mobile-shell .rack-content--img img {
		width: 100%;
	}

	/* Mobile-only float-width cap. Per the owner's direction: keep
	   alignleft/alignright floats in blog posts rather than stacking
	   them full-width, even if that means they render fairly small —
	   the priority is leaving enough column width for the wrapped body
	   text to stay legible. The unscoped .rack-content--blog img rule
	   above already stops oversized floats from overflowing at ANY
	   width; this adds a tighter cap specifically at mobile, where a
	   float at (up to) 100% of a 320-767px column would otherwise
	   leave no room for text beside it. 42% is a starting point, not
	   independently re-derived from any asset — leaves roughly half the
	   column for wrapped text after margins; small floats (already
	   under 42%) are untouched. Tablet intentionally gets no cap (see
	   the tablet block below) — the column is wide enough there that
	   the blanket max-width:100% fix is sufficient, matching how an
	   oversized float already behaves on desktop. */
	.mobile-shell .rack-content--blog img.alignleft,
	.mobile-shell .rack-content--blog img.alignright {
		max-width: 42%;
		height: auto;
	}

	/* .wp-caption (defined near the top of this file, ~line 2909) sets
	   max-width:640px !important but never forces width down — a real
	   post found via the content survey has an inline style="width:
	   1920px" (etc.) on the caption figure, which stays at that fixed
	   px value (clamped only to 640px) regardless of how narrow the
	   column actually is, overflowing at mobile widths.

	   display:block is NOT optional on ANY variant below, found live on
	   a real post: WordPress puts a captioned image's real alignment
	   class (alignleft/alignright/aligncenter) ON THE SAME element as
	   .wp-caption (e.g. <figure class="wp-caption alignright">), so the
	   global, unscoped .alignleft/.alignright rule (=WP Images section,
	   further up this file) ALSO applies here and sets display:inline —
	   a real bug, only on left/right-aligned captions (aligncenter's own
	   rule already sets display:block, and an uncaptioned figure with
	   no align class defaults to block too, which is why only
	   left/right captions broke and centered ones never did). An inline
	   box ignores width entirely and — worse — draws its border as
	   separate fragments per line box instead of one unified border,
	   which is what actually read as "broken": stray bracket-shaped
	   border fragments instead of a real polaroid-style frame around
	   the photo. .mobile-shell .rack-content--blog .wp-caption's
	   3-class selector already outweighs .alignleft/.alignright's
	   single class, so plain display:block here needs no !important to
	   win. */
	.mobile-shell .rack-content--blog .wp-caption {
		display: block;
	}

	/* Centered (or unclassed) captions: treated as a full-width,
	   non-floating block — these read fine as a bigger, standalone
	   photo at any width, confirmed live on real posts. */
	.mobile-shell .rack-content--blog .wp-caption:not(.alignleft):not(.alignright) {
		width: 100% !important;
		float: none;
		margin-left: 0;
		margin-right: 0;
	}

	/* Left/right-aligned captions: a real, owner-reported regression —
	   forcing these to width:100% (the original fix here) stretched
	   the whole bordered card out to the full column width even though
	   the photo itself is much narrower, leaving a big band of empty
	   cream padding around a small centered photo instead of a
	   properly-sized polaroid card. Fixed by treating a captioned
	   float exactly like a plain floated image: the same 42% max-width
	   cap as .rack-content--blog img.alignleft/.alignright below,
	   keeping the real float (left/right, from the global alignleft/
	   alignright rule — not overridden here) instead of forcing it
	   into a block. max-width, not width, so this still correctly
	   clamps an oversized inline style="width:...px" (the original
	   overflow problem this whole rule exists for) while leaving a
	   caption whose own inline width is already narrower than 42%
	   alone, same "small floats stay small" behavior the plain-image
	   cap already has. The image inside still gets max-width:100% from
	   its own size-* class or the unscoped .rack-content--blog img rule
	   above, so it always fills whatever width this box ends up at.
	   !important is required here, not just higher specificity — the
	   base .wp-caption rule's own max-width:640px is ALSO !important
	   (found live: without this, the 640px ceiling won regardless of
	   selector specificity, since !important only loses to another
	   !important declaration, never to a plain one). */
	.mobile-shell .rack-content--blog .wp-caption.alignleft,
	.mobile-shell .rack-content--blog .wp-caption.alignright {
		max-width: 42% !important;
	}

	/* .widestreamingbuttons (defined near the top of this file) is
	   used directly in post content, not applied by any template — a
	   fixed 1000px-wide row of streaming-service logo buttons
	   (/blog/20-years-of-madness), each image a fixed 175px. Owner-
	   reported: not responsive at all, confirmed — no existing rule
	   anywhere makes this fluid. Fixed the same way every other fixed-
	   px post-content component in this file is: fluid container,
	   images converted to a percentage of the container's own now-
	   fluid width. The markup has an explicit <br /> forcing exactly
	   3 buttons per row regardless of viewport (not this CSS's doing),
	   so each image only needs to comfortably fit 3-per-row at the
	   narrowest mobile width — 30% each (vs. 17.5% at desktop's fixed
	   1000px) leaves real gap between them down to 320px. */
	.mobile-shell .rack-content--blog .widestreamingbuttons {
		width: 100%;
		margin-left: 0;
	}

	.mobile-shell .rack-content--blog .widestreamingbuttons img {
		width: 30%;
	}

	/* 20-years-of-madness's "Bonus Vids & Deleted Scenes" two-column
	   video row (the author-authored <div style="display:flex; gap:
	   14px"> — see the unscoped div:has(> iframe)/aspect-ratio rules
	   above) — mobile-only per the owner's explicit ask: keep the real
	   2-up side-by-side layout at desktop/tablet, but stack to one
	   full-width column at mobile, where two ~140px-wide videos side
	   by side read as too tiny to be worth watching. flex-direction:
	   column flips the main axis to vertical, so align-items' default
	   value (stretch) makes each child fill the container's full
	   cross-axis width for free — no explicit width:100% needed on the
	   children for that part. The children's own flex:1 1 0% (added
	   for the row-direction 2-up split, see above) is explicitly
	   neutralized back to flex:0 0 auto here — left as 1 1 0% in
	   column mode, flex-grow could still try to distribute any leftover
	   vertical space between the two stacked videos, which the
	   aspect-ratio rule above has no say over (aspect-ratio governs
	   HEIGHT-FROM-WIDTH, not the flex algorithm's own main-axis growth
	   accounting, and the two are separate mechanisms that don't
	   automatically defer to each other) — flex:0 0 auto removes that
	   ambiguity entirely, letting aspect-ratio be the only thing
	   deciding each video's height. */
	.mobile-shell .rack-content--blog div[style*="display: flex"] {
		flex-direction: column;
	}

	.mobile-shell .rack-content--blog div[style*="display: flex"] > div:has(> iframe) {
		flex: 0 0 auto;
	}

	/* #fulltray: height:0/padding-bottom technique (mobile-tray.gif,
	   628x79, 79/628 = 12.5796%). Needs explicit position:relative +
	   percentage top/left for the buttons — desktop's implicit
	   static-position fallback isn't reliable once the box's declared
	   height is 0. Buttons sit flush at bottom:0 (not centered or
	   top-aligned to the TV icon's own off-center position, x=269-359/
	   y=7-75 of 628x79) — the button's own height doesn't exactly match
	   the icon's, so anything but flush-bottom leaves a visible gap.
	   Button dimensions are percentages of the tray, not fixed px, so
	   they scale with it at every width. */
	.mobile-shell #fulltray {
		background-image: url(/assets/images/structure/mobile-tray.gif);
		background-repeat: no-repeat;
		background-size: 100% 100%;
		width: 100%;
		height: 0;
		padding-bottom: 12.5796%;
		padding-left: 0;
		margin: 0 auto;
		position: relative;
	}

	.mobile-shell .fingerbuttonleft,
	.mobile-shell .fingerbuttonright {
		position: absolute;
		padding-top: 0;
		margin-left: 0;
		width: 15.2866%;
		height: 89.87%;
		bottom: 0;
	}

	.mobile-shell .fingerbuttonleft {
		left: 13.7739%;
	}

	.mobile-shell .fingerbuttonright {
		left: 70.9554%;
	}

	/* Longhand properties only (background-image/position/size/repeat,
	   never the background shorthand) — this exact codebase already
	   hit a bug elsewhere (see "Button textures" in the project
	   handover) where a shorthand declaration's implicit reset of
	   background-repeat/size beat a more-specific rule's longhand
	   override. background-size:300% 100% + positive percentage
	   offsets (0%/50%/100%) is the same sprite technique already
	   established for the hamburger drawer's own thin-button.png —
	   POSITIVE percentages are correct here (not negative) per that
	   section's own documented sign-bug fix. */
	.mobile-shell .fingerbuttonleft a:link,
	.mobile-shell .fingerbuttonleft a:visited {
		background-image: url('/assets/images/structure/fingerbuttonleft.png');
		background-repeat: no-repeat;
		background-size: 300% 100%;
		background-position: 0% 0;
		width: 100%;
		height: 100%;
		display: block;
	}

	.mobile-shell .fingerbuttonleft a:hover {
		background-position: 50% 0;
	}

	.mobile-shell .fingerbuttonleft a:active {
		background-position: 100% 0;
	}

	.mobile-shell .fingerbuttonright a:link,
	.mobile-shell .fingerbuttonright a:visited {
		background-image: url('/assets/images/structure/fingerbuttonright.png');
		background-repeat: no-repeat;
		background-size: 300% 100%;
		background-position: 0% 0;
		width: 100%;
		height: 100%;
		display: block;
	}

	.mobile-shell .fingerbuttonright a:hover {
		background-position: 50% 0;
	}

	.mobile-shell .fingerbuttonright a:active {
		background-position: 100% 0;
	}

	/* .notepaper (defined near the top of this file, ~line 2344) is a
	   general-purpose fan-testimonial/quote card used in post content
	   sitewide, not specific to this rack-content area — fixed
	   width:31.25rem (500px), wider than any phone viewport, so it
	   overflows the now-fluid credits column instead of wrapping.
	   Scoped narrowly to .mobile-shell rather than fixed sitewide
	   (that's a bigger change than this pass, flagged separately) —
	   max-width keeps it at its designed 500px on wider phones,
	   width:100% shrinks it to fit on narrow ones. */
	.mobile-shell .rack-content--credits .notepaper,
	.mobile-shell .rack-content--blog .notepaper {
		width: 100%;
		max-width: 31.25rem;
	}

	/* Closes To-Do item 8 (the standing "#footer mobile crop" gap,
	   deferred since Phase 1 pending the owner building a proper
	   mobile footer container — see HANDOVER.md). This used to be
	   background-size:cover against the same footer.png the tablet
	   fix originally also mis-used cover on (see that fix's own long
	   comment, "/vault + /blog Tablet Layout" → bug #3, for the
	   math) — cover's scale factor there is max(box_width/1100,
	   box_height/46), and with height held at the unscoped desktop
	   rule's fixed 46px, that's max(<1,1)=1 at every mobile width,
	   so cover painted footer.png at its full native 1100px
	   regardless of the actual (much narrower) box and cropped the
	   end caps off both sides — confirmed the identical bug the
	   tablet fix already flagged as "likely also present, not yet
	   fixed" for mobile.

	   Not fixed by just reusing footer.png fluid the way the tablet
	   block does, though: the owner supplied a purpose-built
	   mobile-footer.png (768x79, same "author new art at the mobile
	   canvas width" convention as mobile-header-v0.8.png/
	   mobile-rack-topper.png etc, not footer.png rescaled) with a
	   proportionally taller dark "screen" area than the desktop bar
	   has room for. Same height:0 + padding-bottom aspect-ratio
	   technique as everywhere else in this file either way —
	   79/768 = 10.2865%. */
	.mobile-shell #footer {
		width: 100%;
		height: 0;
		padding-bottom: 8.3333%; /* 64/768 */
		background-image: url(/assets/images/structure/mobile-footer.png);
		background-size: 100% 100%;
		position: relative;
	}

	/* mobile-footer.png went through one height revision after this
	   block first shipped — 768x79 to 768x64 (width unchanged; the
	   owner felt the bar read too tall/wide relative to the copy),
	   heights only. Re-measured, not guessed: 8.3333% = 64/768. Dark
	   "screen" bezel is ~13px top / ~14px bottom either way (the
	   revision shortened the dark screen itself, not the bezel) —
	   still near enough symmetric that centering across the FULL box
	   lands text in the right visual spot, no separate inset needed.
	   If this asset changes again, re-measure rather than assume the
	   bezel scaled proportionally with it. */

	/* The copyright line was wrapping onto a second line at phone
	   width (fixed 16px was sized for the 1100px desktop bar) and
	   overflowing #footer's fixed 46px height when it did. clamp()
	   scales it down to fit one line at any width down to a sane
	   8px floor, and never exceeds the original 16px on the wider
	   end of this range — this part was already correct and needed
	   no changes for the new art; only the box above did.

	   position:absolute + display:flex is needed here — height:0
	   above leaves no real content height for #footer p's/
	   .cg-footer's own fixed line-height:44px (sized for the old
	   46px box) to center within, so the child needs both its own
	   dimensions AND its own vertical-centering mechanism restored.

	   A margin:auto-based, non-flex version of this rule shipped
	   first and was WRONG — worth knowing if this is ever "simplified"
	   back in that direction. The reasoning at the time seemed sound
	   (position:absolute;inset:0;margin:auto 0, no display:flex, on
	   the theory that a flex container splits multi-node inline
	   content — see the real bug below — into separately
	   whitespace-trimmed anonymous items). It shipped, and broke
	   vertical centering completely: per the actual CSS2.1
	   abs-pos-sizing algorithm, the "auto margins split the extra
	   space" resolution only fires when top/height/bottom all have
	   real values — when height is the one left 'auto' (our case),
	   the spec instead resolves height itself to fill the available
	   space and sets any auto margins to 0. Confirmed live via
	   getComputedStyle: height came out as a real px value (matching
	   #footer's own fluid height exactly, i.e. STRETCHED to fill, not
	   shrunk to content), margin-top/bottom both 0 — the text then
	   rendered flush at the TOP of that stretched block, since plain
	   block layout has no automatic vertical-centering behavior for
	   its own inline content. Reported live by the owner ("text is at
	   the top of the screen, not centered, mobile only") and
	   confirmed by directly inspecting computed styles rather than
	   guessing from the CSS text.

	   The actual fix keeps display:flex (which DOES correctly center
	   an auto-height child within a stretched absolutely-positioned
	   box — that part of the original flex version was never broken)
	   and instead fixes the real, shipped whitespace bug a different
	   way: footer.php's markup is "COPYRIGHT 1992-" +
	   <span id="copyright-year"> + " LETHAL FINGER LLC", three
	   separate inline children (two text nodes either side of the
	   year span), not one plain text run — flex wraps EACH of those
	   in its own anonymous flex item, and each item independently
	   trims ITS OWN leading/trailing whitespace per normal CSS
	   white-space:normal/nowrap collapsing rules, which is what ate
	   the space between the year and "LETHAL" (confirmed via
	   getBoundingClientRect on each child node landing flush against
	   its neighbor). white-space:pre (not nowrap) sidesteps this: per
	   spec, 'pre' preserves whitespace verbatim and does not do the
	   line-edge trimming 'normal'/'nowrap' do, so the leading space
	   in that third flex item survives being at the start of its own
	   box. Confirmed live, not assumed: with display:flex restored
	   and nowrap swapped for pre, both the centering AND the space
	   are correct simultaneously (verified via the same
	   getBoundingClientRect-diff technique used to catch the original
	   bug). Doesn't affect wrapping behavior either way — 'pre', like
	   'nowrap', never wraps this text to a second line, which is what
	   actually matters here, not the collapsing behavior on its own.
	   NOT top:50%/transform:translateY(-50%) as an alternative fix
	   for the centering — .cg's own cg-jitter animation (see "Base CG
	   Effect" further down) already drives the transform property on
	   this exact element; a static transform here would just get
	   overridden mid-jitter, undoing the centering ~90% of the time. */
	/* The centering mechanism itself (position/inset/display/
	   align-items/justify-content/line-height/white-space) moved to
	   the base, unscoped .cg-footer rule (see Footer section, near
	   #footer) so desktop shares the exact same technique instead of
	   its own separate line-height trick — this rule now only needs
	   the mobile-specific font-size. */
	.mobile-shell .cg-footer {
		font-size: clamp(8px, 2.4vw, 16px);
	}

	/* Banner: swap the desktop TV-wall GIF for the mobile crop, made
	   sticky so it (and the hamburger icon overlaid on it) stays
	   reachable while scrolling this now-very-long page. #hedsingle is
	   single vault posts' own desktop banner (header-single.php, reused
	   via get_template_part() from header-mobile.php) — same swap, same
	   reasoning, just a different id since single posts never render
	   #hed at all (see header-mobile.php). */
	.mobile-shell #hed,
	.mobile-shell #hedsingle {
		display: none;
	}

	.mobile-shell #hedmobile {
		display: block;
		position: sticky;
		top: 0;
		z-index: 10;
	}

	/* Scoped to #vaultHeaderBg specifically (not a bare `img` selector)
	   now that #hedmobile holds three overlaid pieces — the background
	   art, the TV gif, and the category-label text — and only the
	   background art should stretch to the header's full width. */
	.mobile-shell #hedmobile #vaultHeaderBg {
		width: 100%;
		height: auto;
		display: block;
	}

	/* #vaultNavToggle and #vaultNavToggleActive are both children of
	   #hedmobile now (see header-mobile.php), so position:absolute
	   resolves against the header's own box — #hedmobile's
	   position:sticky already establishes that containing block, and
	   since the button is a real DOM child of the sticky header it
	   scrolls/sticks together with it automatically, no position:fixed
	   trick needed.

	   These coordinates are NOT just the tight bounding box of the
	   three bars themselves (measuring only the dark bar pixels was
	   the mistake in an earlier pass here) — mobile-active-ham-v0.8.png
	   is a 128x115 image where the bars only occupy a 79x67 area
	   *within* that canvas (at local offset 26,25), padded on every
	   side by the rest of the image's own darker "active" background
	   fill. Fitting that whole 128x115 image into a box sized to just
	   the tight bars would visibly shrink it — exactly what happened.
	   The fix: solve for where the active image's own top-left corner
	   must land so that ITS bars (at local 26,25) line up with the
	   background art's real bar position (652,38 in mobile-header-
	   v0.8.png, 768x141 — re-measured for v0.8 with a threshold matched
	   to the one used on the active art below, after an earlier pass
	   here mismatched thresholds between the two measurements and
	   landed 1px low, visibly "too low" once shipped; v0.7's bars sat
	   at 666,38, before the whole right side of the header shifted left
	   to make room for #vaultScrollTopToggle) — i.e. box_left = 652-26,
	   box_top = 38-25, sized to the active image's own full 128x115,
	   not the bars alone:
	     left:   626 / 768 = 81.51%
	     top:    13  / 141 = 9.22%
	     width:  128 / 768 = 16.67%
	     height: 115 / 141 = 81.56%
	   This is also the hit-box for the button itself, on purpose (not
	   just the bars) — a bigger, easier target that matches exactly
	   what lights up as "active". Expressed as percentages (not px) so
	   they stay pixel-perfect as the header scales fluidly with
	   viewport width. */
	.mobile-shell #vaultNavToggle {
		display: block;
		position: absolute;
		left: 81.51%;
		top: 9.22%;
		width: 16.67%;
		height: 81.56%;
		/* Higher than the nav panel's z-index:30 as a safety margin —
		   the panel no longer overlaps the header at all now (see its
		   own comment), but keeping the icon above it regardless costs
		   nothing and guards against any subpixel rounding at the
		   seam. */
		z-index: 40;
		background: transparent;
		border: none;
		padding: 0;
		margin: 0;
		cursor: pointer;
	}

	/* The active-state art (mobile-active-ham-v0.8.png) sits at the
	   exact same coordinates as the button above it, hidden until the
	   button's aria-expanded flips to "true" — assets/js/vault-mobile-
	   nav.js already sets that attribute on toggle, so this is pure
	   CSS, no JS change needed for this swap. pointer-events:none so
	   clicks always land on the real button beneath it, not this
	   decorative image (it's the LAST child, so it paints on top by
	   default DOM order — z-index:21 makes that explicit too). */
	.mobile-shell #hedmobile #vaultNavToggleActive {
		display: none;
		position: absolute;
		left: 81.51%;
		top: 9.22%;
		width: 16.67%;
		height: 81.56%;
		z-index: 41;
		pointer-events: none;
	}

	/* 30mom-tv.gif — links straight home, a separate destination from
	   #vaultHeaderCategoryLabel below (neither is nested in a single
	   header-wide link). Measured directly off the background art's
	   blank left section and the header's content height (y=13 to
	   y=127 of 141):
	     left: 1.69% (13/768, the header's own 13px frame border)
	     top: 9.22% (13/141)
	     width: 20.44% (157/768, the GIF's own native width)
	     height: 80.85% (114/141, the GIF's own native height)
	   Position/size lives on the link; the GIF fills it at 100%/100%. */
	.mobile-shell #vaultHeaderTvLink {
		display: block;
		position: absolute;
		left: 1.69%;
		top: 9.22%;
		width: 20.44%;
		height: 80.85%;
		z-index: 15;
	}

	.mobile-shell #vaultHeaderTvLink img {
		display: block;
		width: 100%;
		height: 100%;
	}

	/* Category-name label, real text linking to this category's own
	   archive — the click target is deliberately the *outer* rounded
	   frame from the background art (including its bezel rim), not
	   just the tight inner dark window the text sits in, though the
	   two are close enough to concentric that centered text still
	   lands visually centered in the inner window:
	     left: 28.91% (222/768), top: 22.70% (32/141)
	     width: 41.15% (316/768), height: 53.19% (75/141)
	   flex-centering, not line-height matching — this box's height is
	   percentage-based, not a fixed px value line-height could match. */
	.mobile-shell #vaultHeaderCategoryLabel {
		display: flex;
		align-items: center;
		justify-content: center;
		position: absolute;
		left: 28.91%;
		top: 22.70%;
		width: 41.15%;
		height: 53.19%;
		z-index: 15;
		/* Don't add text-shadow/animation here — this element also
		   carries class="cg" (see "Base CG Effect"), and this ID-based
		   rule outranks .cg's own lower-specificity values, so declaring
		   either property here would silently override the CRT effect.
		   The one exception (excluding .cg's cg-jitter animation) is
		   handled by the next rule below instead, so the other three
		   animations and the ::before overlay still apply for free.
		   font-size is vw-based against the header's own height, not
		   this box's — this box is the outer click-target frame (see
		   above), sizing off it would size off the wrong reference. */
		font-family: 'quanta', monospace;
		font-size: 4vw;
		color: #fe3527;
		font-weight: 700;
		letter-spacing: .7px;
		text-transform: uppercase;
		text-decoration: none;
	}

	/* .cg bundles cg-jitter (a vertical position jitter) together with
	   cg-flicker/cg-tracking-clip/cg-colordrift in one `animation`
	   shorthand — since a shorthand can't be partially overridden
	   property-by-property, dropping just jitter means re-declaring the
	   other three explicitly, here, at higher specificity (ID + two
	   classes) than plain .cg (one class) so this wins for `animation`
	   specifically while every other .cg property (text-shadow, the
	   ::before overlay, etc.) is untouched and still applies normally. */
	.mobile-shell #vaultHeaderCategoryLabel.cg {
		animation:
			cg-flicker 4s linear infinite,
			cg-tracking-clip 2.5s steps(1) infinite,
			cg-colordrift 6s ease-in-out infinite;
	    	--cg-blur: 0.05em;
	}

	/* .cg::before is position:absolute, so it doesn't inherit this
	   box's flex centering by default — needs the same flex centering
	   here explicitly, or its clip-mask text (meant to sit invisibly
	   under the noise texture) drifts off the real text and shows as a
	   visible grey duplicate. mix-blend-mode:luminosity, not screen —
	   screen only lightens, which washes the red toward pink; luminosity
	   keeps the red text's hue/saturation and lets the noise/scanline
	   layer modulate only brightness. */
	.mobile-shell #vaultHeaderCategoryLabel.cg::before {
		display: flex;
		align-items: center;
		justify-content: center;
		mix-blend-mode: luminosity;
	}

	.mobile-shell #vaultHeaderCategoryLabel:link,
	.mobile-shell #vaultHeaderCategoryLabel:visited,
	.mobile-shell #vaultHeaderCategoryLabel:hover,
	.mobile-shell #vaultHeaderCategoryLabel:active {
		color: #fe3527;
		text-decoration: none;
	}

	.mobile-shell #vaultNavToggle[aria-expanded="true"] + #vaultNavToggleActive {
		display: block;
	}

	/* Scroll-to-top plate, new in v0.8. Box is the small placeholder
	   rectangle baked into mobile-header-v0.8.png between the screen
	   window and the hamburger — measured directly off the source art,
	   matching arrow-panel-open-v0.8.webp/arrow-panel-close-v0.8.webp's
	   own 39x52 canvas almost exactly:
	     left:   561 / 768 = 73.05%
	     top:    43  / 141 = 30.50%
	     width:  39  / 768 = 5.08%
	     height: 52  / 141 = 36.88%
	   Inert by default (no background-art src, pointer-events:none) —
	   the header's own baked-in plate art is the entire "closed" look,
	   nothing here needs to draw anything until assets/js/mobile-nav.js
	   opens it. .vault-scroll-top-open (added/removed by that same
	   script, based on scroll position — see its own comment for the
	   threshold/hysteresis) is what actually makes it tappable. */
	.mobile-shell #vaultScrollTopToggle {
		display: block;
		position: absolute;
		left: 73.05%;
		top: 30.50%;
		width: 5.08%;
		height: 36.88%;
		z-index: 16;
		background: transparent;
		border: none;
		padding: 0;
		margin: 0;
		pointer-events: none;
		cursor: default;
	}

	.mobile-shell #vaultScrollTopToggle.vault-scroll-top-open {
		pointer-events: auto;
		cursor: pointer;
	}

	.mobile-shell #vaultScrollTopArt {
		display: block;
		width: 100%;
		height: 100%;
		pointer-events: none;
	}

	/* Belt-and-suspenders: assets/js/mobile-nav.js removes the src
	   attribute entirely (not just clears it to "") once the close
	   animation finishes, specifically so nothing renders here and
	   mobile-header-v0.8.png's own baked-in plate shows through
	   instead. A real <img> with no src attribute at all should
	   already paint nothing, but this element has explicit width/
	   height (needed while an animation IS loaded), and not every
	   engine handles a sized, src-less <img> identically — this rule
	   makes the no-src state visually inert regardless. */
	.mobile-shell #vaultScrollTopArt:not([src]) {
		visibility: hidden;
	}

	/* Nav panel: pinned to the top of the viewport when open, sized to
	   its own content (not full-screen) — it naturally lands just
	   under where the sticky header sits, covering the header and
	   spilling a little into the top of the first video (the 3x3
	   button grid's own height comes out taller than the header's),
	   while everything below stays untouched/transparent, not a
	   normal-flow element pushing #main down. No background color of
	   its own — the button sprites (opaque) and the hamburger icon's
	   own dark backing are the only opaque things, per the owner's
	   call; with gap:0 below, the buttons already tile edge-to-edge
	   so there's no exposed panel-background pixel to color anyway.
	   Off-screen (not display:none) by default so it can slide into
	   view instead of popping — see the transform/visibility comment
	   below — and assets/js/mobile-nav.js toggles .vault-nav-
	   open on click (and closes on an outside click or Escape).
	   !important on the shared layout properties is needed to outrank
	   the existing #mobiletopmenu{display:block !important} swap rule
	   higher up in this file, which still matches at this width too —
	   this selector's higher specificity (class+id vs. plain id) is
	   what lets it win despite appearing earlier in the file. */
	.mobile-shell #mobiletopmenu {
		display: block !important;
		position: fixed;
		/* Starts at the header's own bottom edge (18.36vw = 141/768,
		   30mom-mobile-v0.7.png's own ratio), not top:0 + padding —
		   an overlapping box would sit above the hamburger/header with
		   a higher z-index, silently eating clicks meant for them.
		   var(--vault-header-bottom, 18.36vw) is set by
		   sizeDrawerRows() in mobile-nav.js from a real
		   getBoundingClientRect() measurement, not the bare vw formula
		   — real Safari rendering drifted from the formula by a few
		   px; the vw value is only a fallback for before JS runs. */
		top: var(--vault-header-bottom, 18.36vw);
		left: 0;
		/* Must stay below #hedmobile's own z-index so the header's
		   opaque art masks the panel's slide-in overlap while opening/
		   closing — #vaultNavToggle/#vaultNavToggleActive stay above
		   both either way. */
		z-index: 5;
		width: 100%;
		/* height:auto is load-bearing: an old, unscoped
		   #mobiletopmenu{height:210px} rule elsewhere in this file (the
		   original 768-1024px transitional bar's own fixed size) still
		   applies unless explicitly overridden here, capping this panel
		   at 210px regardless of real content height on wider
		   viewports. */
		height: auto;
		background: transparent;
		background-image: none;
		padding: 0;
		box-sizing: border-box;
		/* Caps the panel to the room actually left below the header;
		   without this, overflow-y:auto has nothing to activate
		   against, so a short viewport's 3rd row can end up permanently
		   unreachable (position:fixed, no page scroll to reveal it). */
		max-height: calc(100vh - var(--vault-header-bottom, 18.36vw));
		overflow-y: auto;
		/* Rigid translateY, not height/max-height — a compositor-only
		   animation (no layout/paint per frame), and it produces the
		   intended drawer-pulled-out feel (bottom row emerges first)
		   rather than a top-down curtain reveal. visibility's own
		   transition is delayed until the transform finishes closing,
		   so the panel stays visible while sliding away and drops out
		   of tab order only once fully hidden; pointer-events switches
		   off immediately so it stops eating clicks the moment it
		   starts closing. */
		transform: translateY(-100%);
		visibility: hidden;
		pointer-events: none;
		transition: transform 0.25s ease-out, visibility 0s linear 0.25s;
	}

	.mobile-shell #mobiletopmenu.vault-nav-open {
		transform: translateY(0);
		visibility: visible;
		pointer-events: auto;
		transition: transform 0.25s ease-out;
	}

	/* 3 columns x 3 rows — one item is always hidden from this panel
	   only (never removed in PHP), so the untouched 768-1024px
	   transitional bar (this theme's existing, pre-redesign
	   #mobiletopmenu swap, still showing all 10 buttons at that width)
	   is unaffected — only this 767px-and-below panel drops one.
	   Buttons fill their grid cell exactly (width:100%, gap:0) so they
	   touch edge-to-edge with no dead space, matching the owner's
	   "flush, touching" request.

	   Default: hide Main (the header's own TV icon already links home,
	   so a separate Main button read as redundant here) and show
	   Contact — matches every page's behavior before this pair of
	   rules existed. Owner's later ask: everywhere EXCEPT the Main page
	   itself, invert that — show Main in the freed-up top-left slot,
	   hide Contact instead; the Main page keeps the original pairing
	   unchanged (Main hidden, Contact shown). .page-id-44 is the Main
	   page's own WordPress-assigned page ID (confirmed via body_class()
	   during the /Main join, see "Update 20" in HANDOVER.md) — not a
	   slug, WordPress doesn't emit one of those for a plain Page.
	   nav-item-main/nav-item-contact are wahnsinn_top_nav()'s own
	   marker classes (functions.php), added specifically so this
	   doesn't depend on :nth-child position against the item array. */
	.mobile-shell #mobilenavlisttop .nav-item-main {
		display: none;
	}

	.mobile-shell:not(.page-id-44) #mobilenavlisttop .nav-item-main {
		display: block;
	}
	.mobile-shell:not(.page-id-44) #mobilenavlisttop .nav-item-contact {
		display: none;
	}

	.mobile-shell #mobilenavlisttop {
		display: grid;
		grid-template-columns: repeat(3, 1fr);
		/* --vault-row-h is set by assets/js/mobile-nav.js's
		   sizeDrawerRows(), only when the ideal 13vw rows genuinely
		   don't fit the real, currently-visible space below the header
		   — the var()'s own `13vw` fallback is what applies on every
		   normal phone, where JS never bothers overriding it. This used
		   to be pure CSS — `min(13vw, calc((100vh - 19.14vw -
		   1.0417vw) / 3))` — which correctly shrank to fit in this
		   Chromium-based testing tool but not in the site owner's real
		   Safari (confirmed: identical window size, Chrome fit with no
		   scroll, Safari still needed one — across two different CSS
		   mechanisms for applying that same calc()/vh expression, which
		   pointed at the math itself rather than either mechanism).
		   Measuring the real rendered space with
		   getBoundingClientRect()/innerHeight instead sidesteps
		   whatever that cross-engine gap was — real measured pixels,
		   not a theoretical formula. See sizeDrawerRows()'s own comment
		   for the full reasoning. */
		grid-template-rows: repeat(3, var(--vault-row-h, 13vw));
		gap: 0;
		width: 100%;
		height: auto;
		margin: 0;
	}

	/* nav-drawer-btm.png — the drawer's bottom "lip", sitting flush
	   under row 3 (Merch/Contact/The Doc). A pseudo-element rather than
	   real markup so nothing in header-mobile.php needs to change; it's
	   a grid child of #mobilenavlisttop like the buttons, so it needs
	   its own explicit column-span (grid auto-placement would otherwise
	   drop it into a single 1-of-3 cell in a new row, not the full
	   width). 768:8 native ratio -> 1.0417vw tall at full viewport
	   width; this exact figure is also subtracted from the buttons'
	   own height: min(...) above, so the lip is accounted for as real
	   space rather than something that could push the drawer taller
	   than the header-to-viewport-bottom room and force a scrollbar. */
	.mobile-shell #mobilenavlisttop::after {
		content: "";
		display: block;
		grid-column: 1 / -1;
		width: 100%;
		height: 1.0417vw;
		background: url('/assets/images/structure/nav-drawer-btm.png') center / 100% 100% no-repeat;
	}

	/* Buttons are fully fluid — width:100% of their grid cell, height
	   from the classic padding-bottom-percentage technique (height:0
	   plus padding-bottom:50%, matching the sprite's native 200:100
	   per-frame 2:1 ratio) rather than the newer `aspect-ratio`
	   property, which turned out to render inconsistently across
	   browsers for this box (confirmed flush in my own Chromium-based
	   testing, but not for the site owner) — padding-bottom is a
	   20+ year old technique with zero cross-browser edge cases, so
	   switching to it removes that whole class of risk regardless of
	   which engine was actually responsible. Since height is 0 and
	   padding creates the visible box, position:relative + an
	   absolutely-positioned inner <a> is needed to hold the text (see
	   below) — background-size/position, though, size against the
	   full padding box automatically and need no such adjustment.
	   background-size/position use PERCENTAGES (self-relative to the
	   button's own box) instead of px, which is what makes the sprite
	   frame selection stay correctly aligned at any fluid size: at
	   background-size:300% 100%, the 3-frame sheet is always exactly
	   3x the box's own width, and a background-position of -50%/-100%
	   always lands on frame 2/3 regardless of the box's actual
	   rendered pixel size (percentage position = position% x
	   (image-width - box-width); solving that backwards for "one full
	   box-width to the left" gives -50%, and "two box-widths left"
	   gives -100%). */
	/* #mobilenavlisttop prefixed onto every one of these (not just
	   .mobile-shell) is load-bearing, not decorative: the unscoped
	   base rule `#mobilenavlisttop li, #mobilenavlisttop li a
	   {height:100px}` (search that selector further up this file) is
	   an ID selector, which beats a plain class selector regardless of
	   source order — it was silently winning over this rule's own
	   height, the same specificity trap that was pushing the button
	   text off-center before. Adding the #mobilenavlisttop ID here
	   raises this rule to ID+class specificity so it actually wins. */
	.mobile-shell #mobilenavlisttop .mobilebutton,
	.mobile-shell #mobilenavlisttop .currentmobilebutton,
	.mobile-shell #mobilenavlisttop .epmobilebutton,
	.mobile-shell #mobilenavlisttop .currentepmobilebutton {
		float: none;
		width: 100%;
		/* height:100% fills whatever the grid-template-rows track above
		   resolves to (see that rule's comment for why the size lives
		   there now instead of here). min-height:0 + overflow:hidden
		   stay as a defensive backstop against the same grid
		   min-content-growth quirk, in case any engine still tries to
		   grow this item past its track — belt and suspenders, not the
		   primary mechanism anymore. */
		height: 100%;
		min-height: 0;
		overflow: hidden;
		position: relative;
		margin: 0;
		background-size: 300% 100%;
	}

	/* Centers the text via flex instead of the original line-height-
	   matches-box-height trick, since the box's real height now comes
	   from a direct height: min(...) (fluid) rather than a fixed px
	   line-height could reliably match. #mobilenavlisttop is prefixed
	   onto every selector here for the same reason as the height rule
	   above: the unscoped `#mobilenavlisttop li a {display:block;
	   line-height:100px; ...}` base rule is ID-based and was beating
	   this rule's own `display:flex` outright (an ID always beats any
	   number of classes) — meaning align-items/justify-content were
	   silent no-ops the whole time, since they only do anything on a
	   flex/grid container, and text position was actually coming from
	   the old rule's fixed 100px line-height instead. */
	.mobile-shell #mobilenavlisttop .mobilebutton a,
	.mobile-shell #mobilenavlisttop .currentmobilebutton a,
	.mobile-shell #mobilenavlisttop .epmobilebutton a,
	.mobile-shell #mobilenavlisttop .currentepmobilebutton a {
		position: absolute;
		inset: 0;
		/* The old unscoped rule also sets this anchor's height to a
		   flat 100px. With both top/bottom (from inset:0 above) *and*
		   an explicit height all specified, that's an over-constrained
		   box per the CSS2.1 absolute-positioning rules — and explicit
		   height wins, bottom gets silently ignored, so inset:0 never
		   actually stretched this to the parent's real (much shorter)
		   height. height:auto here removes that explicit value, which
		   is what lets top+bottom actually govern the height again. */
		height: auto;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/* thin-button.png / thin-epbutton.png (assets/images/structure/)
	   replace mobilebutton.png / epbutton.png for this panel only —
	   same 3-frame-strip layout (rest/hover/current, left to right),
	   just a shorter/thinner frame (100x39 vs the old 100x50), which
	   is why padding-bottom dropped to 39% above. background-position
	   math (0%/-50%/-100%) is unchanged since it's derived purely from
	   frame count, not pixel dimensions — see the long comment above
	   for the derivation. Declared here (not on the shared, unscoped
	   .mobilebutton/.epmobilebutton rule) so the untouched 768-1024px
	   transitional bar elsewhere on the site keeps the original art. */
	.mobile-shell .mobilebutton {
		background-image: url('/assets/images/structure/thin-button.png');
		background-position: 0% 0;
	}

	.mobile-shell .currentmobilebutton {
		background-image: url('/assets/images/structure/thin-button.png');
		background-position: -100% 0;
	}

	.mobile-shell .epmobilebutton {
		background-image: url('/assets/images/structure/thin-epbutton.png');
		background-position: 0% 0;
	}

	.mobile-shell .currentepmobilebutton {
		background-image: url('/assets/images/structure/thin-epbutton.png');
		background-position: -50% 0;
	}

	/* A legacy unscoped rule (search `.currentmobilebutton a:hover,
	   .currentmobilebutton a:active` further up this file) sets the
	   <a>'s background via the SHORTHAND property — this rule outranks
	   it on background-size/position, but shorthand vs. longhand means
	   the old rule is still the only declaration touching
	   background-image/repeat, and wins those by default. The <a>
	   should never paint its own background at all (only the container
	   does, for every other state) — background-image:none must stay
	   explicit here, or the old desktop-scale sprite bleeds through on
	   hover/active. */
	.mobile-shell .mobilebutton a:hover,
	.mobile-shell .mobilebutton a:active,
	.mobile-shell .currentmobilebutton a:hover,
	.mobile-shell .currentmobilebutton a:active,
	.mobile-shell .epmobilebutton a:hover,
	.mobile-shell .epmobilebutton a:active,
	.mobile-shell .currentepmobilebutton a:hover,
	.mobile-shell .currentepmobilebutton a:active {
		background-image: none;
		background-repeat: no-repeat;
		background-size: 300% 100%;
	}

	.mobile-shell .mobilebutton a:hover,
	.mobile-shell .mobilebutton a:active,
	.mobile-shell .currentmobilebutton a:hover,
	.mobile-shell .currentmobilebutton a:active,
	.mobile-shell .epmobilebutton a:hover,
	.mobile-shell .epmobilebutton a:active,
	.mobile-shell .currentepmobilebutton a:hover,
	.mobile-shell .currentepmobilebutton a:active {
		background-position: -50% 0;
	}

	/* :hover is applied to the container, not the <a> — a descendant
	   :hover inside a continuously filter-animated ancestor (the
	   facebreathe animation on .mobilebutton etc.) doesn't reliably
	   repaint here, even though the computed styles are correct. */
	.mobile-shell .mobilebutton:hover,
	.mobile-shell .mobilebutton:active,
	.mobile-shell .currentmobilebutton:hover,
	.mobile-shell .currentmobilebutton:active,
	.mobile-shell .epmobilebutton:hover,
	.mobile-shell .epmobilebutton:active,
	.mobile-shell .currentepmobilebutton:hover,
	.mobile-shell .currentepmobilebutton:active {
		background-size: 300% 100%;
		background-position: -50% 0;
	}

	/* Text sized off the button's own fluid width rather than a fixed
	   px. No height here anymore — it was this ID selector's
	   height:auto quietly overriding the button rule's own height
	   (ID beats class no matter the source order), which is what was
	   pushing the button text off-center; height is now set once,
	   directly, on .mobilebutton/etc. above. Flex centering on the <a>
	   still handles vertical centering within whatever that height is. */
	.mobile-shell #mobilenavlisttop li,
	.mobile-shell #mobilenavlisttop li a {
		font-size: 5.33vw;
	}

	/* Grid: single column, full viewport width edge-to-edge (not the
	   ~350px native art size — deliberately upscaled past native
	   resolution per the owner's call), stacked with zero gap since
	   the art's own framing already reads as separation between
	   cards. */
	.category-vault .vault3 {
		float: none;
		clear: both;
		padding: 0;
		margin: 0;
		width: 100%;
	}

	/* height:0 + padding-bottom (the classic percentage-aspect-ratio
	   technique) instead of the `aspect-ratio` property — see the
	   long comment on the button rules above for why. 263/350.2 =
	   75.1%. Since height is 0, the <a>/img inside are absolutely
	   positioned to fill the padding box instead of relying on a
	   percentage-height that would resolve against the (zero) content
	   height. */
	.category-vault .preview {
		width: 100%;
		height: 0;
		padding-bottom: 75.1%;
		position: relative;
		margin: 0;
	}

	.category-vault .preview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.category-vault .preview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
	}

	/* Same padding-bottom technique as .preview above — 67/350.2 =
	   19.13%. background-size still works unmodified here since
	   background sizing is relative to the full padding box
	   regardless of content height being 0; only the actual text
	   content (the <a>) needs the absolute-positioning treatment.
	   font-size/word-spacing scale with the box (vw-based) instead of
	   the fixed 21px/-1px desktop values, which read as tiny and
	   off-center against the label art once that art is stretched
	   edge-to-edge. */
	.category-vault .vhssm {
		width: 100%;
		height: 0;
		padding-bottom: 19.13%;
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		padding-left: 0;
		font-size: 6vw;
		word-spacing: -0.29vw;
	}

	.category-vault .vhssm a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
		line-height: normal;
	}
}

/****************************
    End /vault Mobile Layout
**********************************************/

/****************************
    /blog Mobile Layout (Phase 1, reusing /vault's shared mobile-shell
    header/hamburger from the section above — see functions.php
    section 26 for the .mobile-shell body class both categories now
    share. This section only restyles /blog's own archive-grid markup,
    .micro/.cart — the .vault3/.preview/.vhssm rules above are
    vault-only, /blog never renders that markup, see
    loop-customcat.php.)

    Same call as /vault's own mobile grid: single column, full
    viewport width, zero gap, same 767px breakpoint, same height:0 +
    padding-bottom aspect-ratio technique instead of `aspect-ratio`
    (see "Why padding-bottom percentage hack" in Vault Work/
    HANDOVER.md). .cart's background-size used to be an inline
    style="" attribute in loop-customcat.php's blog branch — moved to
    a real CSS rule (search ".cart {" above, outside this media query)
    for the same reason .vhssm's was, so it can be overridden here
    without !important.

    Unlike .vault3/.preview/.vhssm (a <figure> split into two sibling
    boxes, a thumbnail and a separate title spine), .cart is ONE box
    that already contains both the title (.cartspine) and an excerpt
    teaser as two stacked <a> children on desktop. Measured directly
    against a real rendered /blog page (not derived from the CSS
    alone, same discipline as the rest of this file) rather than
    assumed from the desktop rule's own px values, since .cartspine
    is display:block (so its padding-top:45px genuinely adds to flow
    height) while the excerpt's wrapping <a> is a default inline
    element (so that same 45px padding-top, inherited from the shared
    `.cart a` rule, does NOT add to its flow height — vertical padding
    on an inline box doesn't push block content, a real cross-element
    behavior difference easy to miss from the CSS text alone). The
    real numbers: .cartspine occupies the box's own top 50% (69/138px,
    text sitting flush at the boundary, not vertically centered in its
    band — align-items:flex-end below matches that instead of the
    center alignment .vhssm used, since that's what actually renders
    on desktop); the excerpt anchor occupies roughly 50%-63.8%
    (19/138px, hugging the top of ITS band — align-items:flex-start).
    Font sizes convert to vw the same way .vhssm's did: px / .cart's
    own 532px native width — 24px title -> 4.5vw, 14px excerpt -> 2.6vw.
**********************************************/

@media (max-width: 767px) {
	.category-blog .micro {
		float: none;
		clear: both;
		margin: 0;
		width: 100%;
	}

	.category-blog .cart {
		width: 100%;
		height: 0;
		padding-bottom: 25.94%; /* 138/532 */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
	}

	.category-blog .cart a {
		position: absolute;
		left: 0;
		right: 0;
		display: flex;
		justify-content: center;
		padding: 0;
	}

	/* font-size/word-spacing/letter-spacing below carry an extra 0.92
	   safety factor on top of the exact desktop ratio (4.5vw/-0.19vw/
	   0.038vw would be the exact match) — desktop's own tightest real
	   case already uses ~99.8% of its available line width, so an
	   exact proportional match has near-zero margin against
	   engine-to-engine text-shaping variance (real 3-line wraps showed
	   up in real Safari/Chrome that this project's own testing tooling
	   never reproduced). 0.92 trades a small text-size reduction for
	   real headroom instead. Tablet is untouched — renders correctly
	   already. */
	.category-blog .cartspine {
		top: 0;
		height: 50%; /* 69/138 */
		align-items: flex-end;
		font-size: 4.14vw; /* 4.5 * 0.92 safety factor - see comment above */
		word-spacing: -0.175vw; /* -0.19 * 0.92 */
		letter-spacing: 0.035vw; /* 0.038 * 0.92 */
	}

	/* padding-top separates the excerpt from the title above (both
	   otherwise meet flush at the shared 50% boundary). A vw value,
	   not %: percentage padding resolves against the containing
	   block's WIDTH, not height, so % wouldn't scale like every other
	   vertical measurement here. */
	.category-blog .cart a:not(.cartspine) {
		top: 50%; /* 69/138 */
		height: 13.77%; /* 19/138 */
		align-items: flex-start;
		padding-top: .8vw;
	}

	/* No truncation/line-clamp — the excerpt renders fully, same as
	   desktop. `.cart p` inherits unscaled word-spacing (-1px, from
	   the desktop `.cart` rule) and letter-spacing (0.2px, from the
	   site-wide base `p` rule) — both must stay re-expressed as vw
	   here (matching .cartspine's own scaling) or the 3-line overflow
	   this caused returns. overflow-wrap:break-word is a narrow safety
	   net for a single run wider than the whole box (e.g. an
	   unbroken "…[The" citation fragment) — normal spec wrapping
	   still governs everything else. Same 0.92 safety factor as
	   .cartspine above — see that rule's own comment. */
	.category-blog .cart p {
		width: 100%;
		padding: 0 6.58%; /* 35/532, matching .cart p's desktop side padding */
		margin: 0;
		font-size: 2.39vw; /* 2.6 * 0.92 safety factor - see .cartspine's comment above */
		word-spacing: -0.175vw; /* -0.19 * 0.92 */
		letter-spacing: 0.035vw; /* 0.038 * 0.92 */
		line-height: normal;
		text-align: center;
		overflow-wrap: break-word;
	}
}

/****************************
    End /blog Mobile Layout
**********************************************/

/****************************
    /episodes Mobile Layout (Phase 1, reusing the shared mobile-shell
    header/hamburger from the section above — see functions.php
    section 26 for the .mobile-shell body class /vault, /blog, and
    /episodes now all share. This section only restyles /episodes' own
    archive-grid markup, .epcon/.vhsl — the .vault3/.preview/.vhssm and
    .micro/.cart rules above are vault/blog-only, /episodes never
    renders that markup, see loop-customcat.php.)

    Simpler conversion than either /vault or /blog: .epcon/.vhsl is
    already a single full-width (1074px) item per row on desktop, not
    a multi-column grid, so there's no column count to change — just
    the same fixed-1074px -> fluid conversion every other box in this
    file gets. .vhsl's background-size used to be an inline style=""
    attribute in loop-customcat.php's episodes branch — moved to a
    real CSS rule (search ".vhsl {" above, outside this media query)
    for the same reason .vhssm's and .cart's were, so it can be
    overridden here without !important.

    .vhsl is ONE box (unlike .vault3's separate .preview/.vhssm
    sibling split) — background art plus a single centered title link,
    the same shape .vhssm already established a fluid technique for,
    just without a second sibling box to coordinate against. 191/1074
    = 17.78% for the padding-bottom aspect-ratio box (see "Why
    padding-bottom percentage hack" in Vault Work/HANDOVER.md);
    62/1074 = 5.77vw for the desktop 62px font-size; -1px/1074 =
    -0.093vw for the desktop -1px word-spacing. Desktop's line-height:
    190px vertical-centering trick doesn't survive going fluid (a
    fixed line-height can't track a variable box height), so the link
    gets the same absolute-position + flex-centering treatment
    .vhssm a's mobile rule already uses.
**********************************************/

@media (max-width: 767px) {
	.category-episodes .epcon {
		float: none;
		clear: both;
		margin: 0;
		width: 100%;
	}

	.category-episodes .vhsl {
		width: 100%;
		height: 0;
		padding-bottom: 17.78%; /* 191/1074 */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		font-size: 5.77vw; /* 62/1074 */
		word-spacing: -0.093vw; /* -1px/1074 */
		line-height: normal;
	}

	.category-episodes .vhsl a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
	}
}

/****************************
    End /episodes Mobile Layout
**********************************************/

/****************************
    /music Mobile Layout (Phase 1, reusing the shared mobile-shell
    header/hamburger from the /vault Mobile Layout section above — see
    functions.php's wahnsinn_add_mobile_shell_body_class() for the
    .mobile-shell body class /vault, /blog, /episodes, and /music now
    all share. This section only restyles /music's own archive
    markup — .musicplayer (an empty, background-image-only div, a
    placeholder for a future JS music player) and .musicshelf/
    .rackmountplacer/.rackmountplacer img (the per-post cassette-
    thumbnail "shelf" — see loop-customcat.php's music branch and the
    unscoped .musicplayer/.musicshelf/.rackmountplacer rules above,
    outside this media query, for the desktop original). /music
    SINGLES are explicitly NOT part of this join — see the docblock on
    wahnsinn_add_mobile_shell_body_class() in functions.php.

    .musicplayer: height:0 + padding-bottom:24.68% (270/1094, the
    panel art's own native ratio) — same padding-bottom aspect-ratio
    technique as everywhere else in this file (see "Why padding-bottom
    percentage hack" in Vault Work/HANDOVER.md) — background-size:100%
    100% stretches imradio-rack.png to fill it (100% 100%, not cover —
    same reasoning as the #footer cover-vs-crop bug fixed elsewhere in
    this file: the box's aspect ratio here is forced to match the
    art's own via padding-bottom, so a plain stretch is correct and
    cover would need the exact same crop-preventing justification
    cover was rejected for there).

    .musicshelf/.rackmountplacer are already a "block containing only
    a float, no real height of its own" shape on desktop (see their
    unscoped rules above) — the current "two columns" is just two
    537px images floating side by side inside a 1074px-wide desktop
    container (2 x 537 = 1074 exactly, no gutter), not any grid/column
    class. Going to one column on mobile is therefore just float:none
    + width:100% on the <img> itself; height stays auto, so the
    image's own aspect ratio is preserved for free, same as how a
    real <img>/<video> already gets this for free elsewhere in this
    file (see the video/iframe embed section of Vault Work/
    HANDOVER.md). ===== */

@media (max-width: 767px) {
	.category-music .musicplayer {
		width: 100%;
		height: 0;
		padding-bottom: 24.68%; /* 270/1094 */
		background-size: 100% 100%;
		margin: 0;
	}

	.category-music .musicshelf,
	.category-music .rackmountplacer {
		width: 100%;
		margin: 0;
	}

	.category-music .rackmountplacer img {
		float: none;
		width: 100%;
		/* Desktop's float:left implicitly blockifies the img per spec
		   (a floated element's computed display is always block), which
		   is what was actually suppressing the ~6px inline-image
		   line-box gap there all along — nothing declared it on
		   purpose. float:none above undoes that side effect too, so the
		   img reverts to its default inline display and the gap comes
		   back. Confirmed via getBoundingClientRect: each .musicshelf
		   box was 65.5px tall against a 59.2px image, a uniform ~6.3px
		   gap under every tape — invisible after the first one only
		   because that specific cassette's own art has a near-black
		   bottom edge blending into the page's black background, not
		   because the gap itself was smaller there. display:block
		   removes the line box (and the gap) outright. */
		display: block;
	}
}

/****************************
    End /music Mobile Layout
**********************************************/

/****************************
    /gallery Mobile Layout (the landing page only — loop-page.php's
    .albumgallery, not any of the five category archives it links to,
    which stay out of scope for now). Reuses the shared .mobile-shell
    header/hamburger/nav-bar wholesale, same as every other join — the
    only new CSS here is .albumgallery/.albums/.albums img themselves.

    Closest cousin is /episodes: five .albums links, each wrapping one
    full-width "spine" <img> (photos.png/flyers-1.png/artwork-1.png/
    gifs-lg.png/20yom-pics.png, all natively 1045x147) stacked in a
    single column — there's no column count to convert, same shape as
    .vhsl, and unlike .vhsl these are real <img> tags, not a
    background-image div, so width:100%/height:auto is all the sizing
    needs (no padding-bottom aspect-ratio box, no vw-based font-size —
    there's no text baked into the box itself, the label is inside
    each PNG's own artwork). single-30mom is added to #container by
    page.php only when is_page('gallery') (see that file) so this
    reuses the exact same .mobile-shell .single-30mom #content rule
    every other joined page's fluid width already comes from, rather
    than inventing a second mechanism.

    The nth-of-type margin-top/clip-path overrides below are NOT
    decorative choices, they're required — the unscoped desktop rule
    (search ".albumgallery .albums:nth-of-type" above) hides each
    spine's own soft, partially-transparent edge fade by overlapping a
    fixed number of PX (measured directly off each PNG's real alpha
    channel at its native 1045x147 size) into the image above/below
    it. Left as fixed px here, that overlap would be proportionally
    huge once these images go fluid and shrink toward phone width —
    at ~375px (roughly a third of the ~1087px these render at on
    desktop) a -12px overlap tuned for the desktop size would eat
    into real artwork, not just the fade. Re-derived as a percentage
    of each image's own native dimensions instead (px÷1045 for the
    margins, which resolve against the containing block's width —
    same width the image itself is fluidly set to here, so the two
    track together; px÷147 for the clip-path insets, which per spec
    resolve against the box's height on the top/bottom sides) so the
    overlap scales down together with the image at any width instead
    of staying a fixed, eventually-too-large amount. ===== */

@media (max-width: 767px) {
	.mobile-shell .albumgallery {
		margin: 0;
	}

	/* .albumgallery .albums (not bare .mobile-shell .albums) — rescoped
	   from a bare .mobile-shell .albums selector: sidebar-custom.php's
	   homepage sidebar ALSO has a .albums class (the photos/flyers/
	   artwork/gifs/doc icon links), a different, much smaller image
	   (344px vs these 1045px spines) with no shared geometry at all.
	   A bare selector here would leak these gallery-tuned negative
	   margins/clip-paths onto that sidebar row the moment Main also
	   carries .mobile-shell — see /Main Mobile Layout further down for
	   the sidebar's own, separately-scoped .albums rule. */
	.mobile-shell .albumgallery .albums {
		display: block;
		width: 100%;
	}

	.mobile-shell .albumgallery .albums img {
		width: 100%;
		height: auto;
	}

	/* :nth-child(N of .albums), not :nth-of-type(N) — counts position
	   among .albums siblings specifically, same defensive reasoning as
	   /Main Tablet Layout's .thevault rule further down. */
	.mobile-shell .albumgallery .albums:nth-child(2 of .albums) img {
		margin-top: -1.1483%; /* -12/1045 */
	}
	.mobile-shell .albumgallery .albums:nth-child(3 of .albums) img {
		margin-top: -1.6268%; /* -17/1045 */
	}
	.mobile-shell .albumgallery .albums:nth-child(4 of .albums) img {
		margin-top: -0.9569%; /* -10/1045 */
	}
	.mobile-shell .albumgallery .albums:nth-child(1 of .albums) img {
		margin-top: -0.6699%; /* -7/1045 */
		clip-path: inset( 4.7619% 0 0 0 ); /* 7/147 */
	}
	.mobile-shell .albumgallery .albums:nth-child(5 of .albums) img {
		margin-top: -0.8612%; /* -9/1045 */
		margin-bottom: -0.5742%; /* -6/1045 */
		clip-path: inset( 0 0 4.0816% 0 ); /* 6/147 */
	}
}

/****************************
    End /gallery Mobile Layout
**********************************************/

/****************************
    /merch Mobile Layout (Phase 1, reusing the shared mobile-shell
    header/hamburger/nav-bar wholesale — the only new CSS here is the
    archive restyle, .rackmountmerch/.rackmountmerch img (see
    loop-customcat.php's merch branch and the unscoped .rackmountmerch
    rules above, outside this media query, for the desktop original).
    /merch SINGLES needed no archive-grid-style work at all — see the
    docblock on wahnsinn_add_mobile_shell_body_class() in functions.php
    and the note at the end of this block.

    Closest cousin is /music, not /vault or /blog: .rackmountmerch has
    no title/caption at all (not even /music's bare placeholder div),
    and on desktop it's the exact same "no real grid" shape /music's
    own .rackmountplacer turned out to be once actually measured — the
    unscoped .rackmountmerch rule floats its own <img> left at a fixed
    538px with no width set on the <figure> itself, so two of them
    just happen to land side by side (538 x 2 = 1076, close enough to
    #content's 1100px that the figure's own 12.5px left padding (see
    below) accounts for the rest) rather than being driven by any
    grid/column class. That made this a pure width/float conversion,
    same as /music's.

    .rackmountmerch's own padding: 0 0 0 12.5px (the desktop gutter
    between columns) is DROPPED entirely here, not converted to a
    percentage — matching /vault's own .vault3 precedent exactly (same
    12.5px number, same float-left-figure-with-left-padding shape,
    see "/vault archive grid" above and in the Tablet Layout section
    below): "zero gutter, matching the mobile grid's own flush,
    touching precedent" instead of reintroducing it fluid. ===== */

@media (max-width: 767px) {
	.category-merch .rackmountmerch {
		padding: 0;
		margin: 0;
	}

	.category-merch .rackmountmerch img {
		float: none;
		width: 100%;
		height: auto;
		/* Desktop's float:left implicitly blockifies the img per spec
		   (floating always computes display to block) — that's what
		   was suppressing the inline-image line-box gap underneath it
		   all along, same root cause already found and fixed on
		   /music's .rackmountplacer img (see "/music Mobile Layout"
		   above). float:none here undoes that side effect the same
		   way, so this gets the identical display:block fix proactively
		   rather than waiting for it to ship as a visible bug again. */
		display: block;
	}
}

/****************************
    End /merch Mobile Layout
**********************************************/

/* /merch SINGLES: almost no new rules needed anywhere in this file.
   catsingle.php's blog/merch branch (see that file) renders
   .rack-content--blog for merch posts identically to blog posts — not
   a merch-specific class — so every mobile/tablet rule the /blog
   Singles join already wrote (.rack-cap--wide/.rack-paper--wide
   mobile+tablet chrome, .rack-content--blog's image/float/caption/
   embed CSS, #fulltray/finger-buttons) is class-scoped, not
   category-scoped, and already reaches merch singles the instant the
   wahnsinn_add_mobile_shell_body_class()/header.php gates above open
   for them — the exact same "extends for free" pattern already
   confirmed for /music singles riding vault/episodes' Phase B work.
   The one exception is the [wahnsinn_grid] mobile-column rule right
   below — not merch-specific either (it's the shortcode's own class,
   reachable from any category), it just happens that the "Hoofsip
   Subscriptions" merch post is this shortcode's first live user to
   actually need it. */

/* .wahnsinn-grid mobile column fallback — [wahnsinn_grid]'s own
   --wahnsinn-grid-cols-mobile custom property (functions.php,
   wahnsinn_grid_shortcode()), not a category-specific rule. Added
   after the "Hoofsip Subscriptions" merch post's 6-column grid
   measured at ~53px per cover on a 375px phone. Deliberately NOT an
   !important override of --wahnsinn-grid-cols (the desktop value,
   also set inline, would need it to lose) — the shortcode emits a
   SECOND inline custom property instead, so this rule and the
   unscoped desktop rule each just read their own property name, no
   specificity/cascade fight. See the shortcode's own doc comment for
   why a single blanket mobile column count wouldn't fit every live
   usage (some already-published grids use cols="2", where a generic
   "3 on mobile" would be a strange upgrade, not a fix) and for the
   min(cols,3) default that makes this apply automatically to every
   existing shortcode call without editing any post content.
   .mobile-shell-scoped like every other new-responsive-behavior rule
   in this file — .wahnsinn-grid could theoretically appear on a
   not-yet-joined category's post (none do today, confirmed via a DB
   survey), and this keeps it from doing anything there until that
   category is actually joined. */
@media (max-width: 767px) {
	.mobile-shell .wahnsinn-grid {
		grid-template-columns: repeat(var(--wahnsinn-grid-cols-mobile, 3), 1fr);
	}
}

/****************************
    /photos Mobile Layout — reuses the shared .mobile-shell header/
    hamburger/nav-bar/footer/rack-frame wholesale (the .rack-cap--wide/
    .rack-paper--wide frame this archive is wrapped in, see
    category.php's gallery-cat branch, already got full mobile+tablet
    fluid CSS from the /blog Singles join — nothing new needed there).
    The only new CSS is this grid itself.

    .rack-content--gallery/.masonry-item is a SHARED class, not
    photos-specific — /artwork, /flyers, and /doc all reuse this exact
    markup too (category.php's is_category(array('artwork','flyers',
    'photos','doc')) gallery-cat branch, loop-customcat.php's matching
    branch). Deliberately .mobile-shell-scoped here, not
    .category-photos-only, matching the .rack-content--blog precedent
    (shared by /blog and /merch) — when artwork/flyers/doc get their
    own mobile-shell join later, they inherit this exact grid treatment
    for free, no rewrite needed.

    Desktop is a plain CSS column-count:4 multi-column layout (no
    grid/flex, no fixed per-item width) — 2 columns at mobile per the
    owner's ask. Gutters stay proportional to the desktop 13px value
    rather than going flush/edge-to-edge like most other grids in this
    file (explicit owner call, unlike /vault's .vault3 precedent):
    column-gap and margin/padding accept percentages, resolving against
    the container's own width same as any other box-model property, so
    13/1045 = 1.2440% carries the exact desktop ratio through at any
    width in this rule without a separate vw-based correction factor —
    unlike text sizing elsewhere in this file (e.g. /blog's 0.92 mobile
    safety factor), a plain box-model percentage needs none of that
    compounding-inset math. ****************************/

@media (max-width: 767px) {
	.mobile-shell .rack-content--gallery {
		column-count: 2;
		column-gap: 1.2440%; /* 13/1045 */
		padding: 1.2440% 0;
	}

	.mobile-shell .masonry-item {
		margin: 0 0 1.2440% 0;
	}
}

/****************************
    End /photos Mobile Layout
**********************************************/

/****************************
    /gifs Mobile Layout — reuses the shared .mobile-shell header/
    hamburger/nav-bar/footer/rack-frame wholesale, same as every join.
    Unlike /photos/artwork/flyers/doc, /gifs does NOT share
    .rack-content--gallery/.masonry-item — loop-customcat.php's own
    docblock is explicit that /gifs gets its own dedicated branch,
    reusing <figure class="vault3"> (literally /vault's own outer
    wrapper class, not a lookalike) with a single .gifpreview box
    inside instead of /vault's .preview+.vhssm split. Simpler than
    /vault's own join for the same reason /photos was simpler than
    /blog's: no caption/title text on the grid at all, so none of the
    vw-based font-size/word-spacing correction-factor math /vault's
    own .vhssm needed here.

    Deliberately a NEW rule, not an edit to /vault's own
    .category-vault .vault3 selector above — same "a join gets its own
    rule, not an edit to another category's already-working selector"
    discipline this project has followed since /merch reused .vault3's
    12.5px-gutter-drop precedent as a new rule rather than touching
    it. 1 column at mobile, matching /vault's own precedent exactly
    (float:none, zero gutter, flush edge-to-edge). ****************************/

@media (max-width: 767px) {
	.category-gifs .vault3 {
		float: none;
		clear: both;
		padding: 0;
		margin: 0;
		width: 100%;
	}

	/* object-fit:cover, not letterboxing (desktop's own technique) —
	   some GIFs' native ratio leaves a visible black gap under
	   letterboxing at this width. 75.1571% (263.2/350.2) is NOT
	   .preview's near-identical-but-different 75.1% (263/350.2) — two
	   separately-measured boxes, don't assume they're the same number
	   if either is ever re-measured. */
	.category-gifs .gifpreview {
		width: 100%;
		height: 0;
		padding-bottom: 75.1571%; /* 263.2/350.2 */
		position: relative;
		margin: 0;
	}

	.category-gifs .gifpreview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.category-gifs .gifpreview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		display: block;
	}
}

/****************************
    End /gifs Mobile Layout
**********************************************/

/****************************
    /zines Mobile Layout — reuses the shared .mobile-shell header/
    hamburger/nav-bar/footer/rack-frame wholesale, same as every join.
    Singles ride catsingle.php's zines branch (.rack-cap--narrow/
    .rack-paper--narrow/.rack-content--zines — the same NARROW rack
    family vault/episodes/music share), so Phase B needed zero new CSS
    here, only the gate extension in functions.php/header.php — see
    that function's own doc comment for the full "extends for free"
    confirmation.

    The archive is the real work: loop-customcat.php's generic
    is_category() fallback branch renders <figure class="vault3">
    <div class="boxpreview">...</div></figure> — the confirmed-intended
    display for zines (NOT a bug — an old "xzines" typo once meant to
    route zines through a different, now-superseded #fullwrap layout,
    but the site owner confirmed 2026-06-25 this generic boxpreview
    fallback is the real, intended look; see the .boxpreview rule's own
    comment further up). Closest cousin is /gifs: same single-image-box
    .vault3 shape, no caption/title text, so none of /vault's own
    .vhssm vw-based text-sizing math is needed. Deliberately a NEW rule,
    not an edit to /vault's or /gifs' own .vault3 selectors — same
    discipline this project has followed since /merch. 1 column at
    mobile, matching /vault's/gifs' own precedent exactly (float:none,
    zero gutter, flush edge-to-edge).

    Cover images use object-fit:cover, not the letterbox technique
    (max-width/max-height:100%;margin:auto) — more robust across
    browsers, and real cover images crop virtually nothing under it
    since their own ratios are already close to the box's.

    The row gap lives on `.vault3`'s own `margin-bottom`, not a nested
    child's (e.g. `.boxpreview`) — percentage margins/padding resolve
    against an element's OWN containing block, and once a parent (here,
    `.vault3`) has its own padding for a column gutter, its content box
    is narrower than its outer width, so a child's percentages and the
    parent's own percentages stop meaning the same pixel amount even
    at an identical CSS value. If you ever add per-column padding to
    another float-grid `.vault3` variant, put matching row-gap spacing
    on `.vault3` itself, not a nested child. ****************************/

@media (max-width: 767px) {
	.category-zines .vault3 {
		float: none;
		clear: both;
		padding: 0;
		margin: 0 0 4.2833% 0; /* 15/350.2 — row-to-row gap, on .vault3 itself (not .boxpreview) so it always shares .vault3's own containing block, see the block comment above */
		width: 100%;
	}

	.category-zines .boxpreview {
		width: 100%;
		height: 0;
		padding-bottom: 129.0691%; /* 452/350.2 — image-content-area ratio only, the row gap lives on .vault3 now */
		position: relative;
		margin: 0;
	}

	.category-zines .boxpreview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.category-zines .boxpreview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		display: block;
	}

	/* .wahnsinn-hoofsip-grid — [wahnsinn_hoofsip_grid]'s own class, not
	   category-specific (it's embedded in the HOOFSIP hub post's content
	   and, via the same shortcode, every individual issue's "Browse &
	   Download Single Issues" section too — reachable from any zines
	   single once this join's gate opens). Originally shipped 4 columns
	   at both mobile AND tablet (only the archive's own .vault3/.boxpreview
	   dropped columns) — revised in a 2026-07-31 follow-up: mobile drops
	   to 2, tablet to 3 (see the Tablet Layout block further down),
	   desktop stays 4.

	   .wahnsinn-hoofsip-grid-title/-summary sizing is vw-based, with a
	   wrinkle other text-bearing grids in this file don't have: this
	   grid's own column COUNT changes per breakpoint (4/3/2), not just
	   its overall width, so the desktop ratio being preserved is
	   font-size-to-COLUMN-width, not font-size-to-grid-width — derived
	   as (desktop_px / 149) × 100 / column_count_at_this_breakpoint.
	   Carries a 0.90 safety factor (independent of /blog's own 0.92)
	   on font-size/line-height/height/padding together, keeping the
	   "5 lines fit in this height" ratio intact — an exact desktop
	   match clipped real summary text via overflow:hidden at narrow
	   widths, the same class of wrapping-margin problem /blog's own
	   excerpt text hit. .wahnsinn-hoofsip-grid-cover img uses
	   aspect-ratio rather than this file's usual padding-bottom
	   technique — fine here since it's a self-contained box with no
	   sibling needing pixel-perfect alignment. */
	.mobile-shell .wahnsinn-hoofsip-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	.mobile-shell .wahnsinn-hoofsip-grid-title {
		font-size: 4.2282vw; /* 14/149 × 100/2 × 0.90 safety factor */
		line-height: 4.8322vw; /* 16/149 × 100/2 × 0.90 */
		padding: 0.906vw 1.8121vw; /* 3/149, 6/149 × 100/2 × 0.90 */
	}

	.mobile-shell .wahnsinn-hoofsip-grid-summary {
		height: 25.3691vw; /* 84/149 × 100/2 × 0.90 */
		font-size: 3.6242vw; /* 12/149 × 100/2 × 0.90 */
		line-height: 4.8322vw; /* 16/149 × 100/2 × 0.90 */
		padding: 0 1.8121vw 1.2081vw; /* 6/149, 4/149 × 100/2 × 0.90 */
	}
}

/****************************
    End /zines Mobile Layout
**********************************************/

/****************************
    /Contact Mobile Layout — reuses the shared .mobile-shell header/
    hamburger/nav-bar/footer/wide-rack-frame wholesale, all already
    class-scoped (not category- or page-specific) from earlier joins.
    text.php ("Template Name: Text") already puts .single-30mom on
    #container unconditionally for all six pages that share it, so
    the .mobile-shell .single-30mom #content fluid-width rule (see
    the /vault Mobile Layout block above) applies the instant the
    body class lands — no template change needed there, unlike
    /gallery's own page.php conditional.

    The one genuinely new rule: .rack-content--text (the_content()
    for text.php's pages) had no responsive <img> rule at all —
    matters here because the real /contact page embeds a small
    spinning-smiley GIF (.rotating-css, see that class further up
    this file) next to the email address. .mobile-shell-scoped
    rather than unscoped like .rack-content--credits'/.rack-content--
    blog's own versions of this same defensive fix — .rack-content--
    text is shared by five other text.php pages (20 Years of
    Madness, Photos, No Access, 20YOM Pics, Artwork) that stay out
    of scope for this join, same reasoning as .rack-content--img's
    own .mobile-shell scoping (it's shared with artifacto.php).
**********************************************/
@media (max-width: 767px) {
	.mobile-shell .rack-content--text img {
		max-width: 100%;
		height: auto;
	}
}
/****************************
    End /Contact Mobile Layout
**********************************************/

/****************************
    /404 Mobile Layout — 404.php never calls get_header() at all, so
    it doesn't ride any of the shared .mobile-shell header/hamburger
    plumbing "for free" the way every join above does; the
    #hedmobile markup is duplicated directly into 404.php itself
    (see that file), reusing the exact same ids so the CSS below and
    assets/js/mobile-nav.js work identically with zero JS changes.

    #hed (darkheader.jpg, the multiscreen/"?" banner) needs no
    override at all here — the owner confirmed mobile should NOT
    show that image, only tablet/desktop, so it stays behind the
    same generic .mobile-shell #hed, #hedsingle{display:none} rule
    every other join already gets (further up this block). Mobile
    content is just #hedmobile (nav), then the sidebar graphic, then
    the footer — #content itself renders nothing (an empty <figure>).

    #leftmenu/.sidebargif/.one-column#container are shared with
    main.php/main-im.php (the still-deferred homepage, see the
    Roadmap in HANDOVER.md) — .mobile-shell alone would already be
    safe to use here (neither of those two templates is
    .mobile-shell-joined yet, confirmed via grep), but .error404 is
    added anyway, matching this project's own "a join gets its own
    new rule, not an edit to a shared selector, even when currently
    safe" discipline (see /gifs' own precedent) — so a future Main
    page join can write its own treatment for this exact layout
    shape without this rule silently reaching it too. */
@media (max-width: 767px) {
	/* Desktop lays #leftmenu + #container side by side via flex (see
	   .main-columns' own desktop rule) — stacked here instead, since
	   #leftmenu's fixed 350.2px plus #container's own 725px min-width
	   floor add up to well over any phone's viewport. gap:0 — the
	   owner's explicit call: the two stacked images (.wrap's 404.gif,
	   then the sidebar gif) should sit flush against each other, no
	   breathing room between them. */
	.mobile-shell.error404 .main-columns {
		flex-direction: column;
		gap: 0;
	}

	.mobile-shell.error404 #leftmenu {
		width: 100%;
		margin-left: 0;
	}

	/* #leftmenu li img's own display:block fix applies here too via the
	   plain (not .error404-qualified) .mobile-shell #leftmenu li img
	   rule under "/Main Mobile Layout" below — one class already beats
	   the legacy unscoped #leftmenu li img{width:344px} rule's
	   specificity, so no .error404 qualifier is needed. */

	.mobile-shell.error404 .sidebargif {
		width: 100%;
		margin-left: 0;
	}

	/* Drops the desktop flex:1/min-width:725px floor entirely.
	   order:-1 (default is 0, same as #leftmenu, which needs no
	   change) moves this ahead of #leftmenu in the stacked column —
	   #leftmenu comes FIRST in the actual DOM (see 404.php), but the
	   owner wants #container's own .wrap content (see below) to
	   render first visually, sidebar gif last, right above the
	   footer. Flexbox order was chosen over reordering the markup
	   itself, since .main-columns' DOM order is shared with the
	   still-deferred main.php/main-im.php (see the Roadmap in
	   HANDOVER.md) — this way nothing about their future layout is
	   presupposed by a 404-only visual reorder. */
	.mobile-shell.error404 #container.one-column {
		flex: none;
		width: 100%;
		min-width: 0;
		order: -1;
	}

}
/****************************
    End /404 Mobile Layout
**********************************************/

/* .sidebarbottom is hidden entirely at mobile+tablet (the owner's
   explicit call, not just fluid). .wrap — 404.php's #content isn't
   actually empty the way it looks from the markup (<figure
   class="wrap"></figure>, no children); it's a real, visible 710x500
   CSS background-image box (404.gif), needing the same height:0/
   padding-bottom aspect-ratio-lock technique this file uses
   everywhere else for a fixed-box background-image element.
   .artifactowrap .rack-content--img — see "/Artifacto Mobile Layout"
   above for the 900/984 ratio's own reasoning. Shared across both
   breakpoints in one rule since none of these three vary between
   them. */
@media (max-width: 1024px) {
	.mobile-shell.error404 .sidebarbottom {
		display: none;
	}

	.mobile-shell.error404 .wrap {
		width: 100%;
		height: 0;
		padding-bottom: 70.4225%; /* 500/710 */
	}

	.mobile-shell .artifactowrap .rack-content--img {
		width: 100%;
		margin-left: 0;
		position: relative;
		height: 0;
		padding-bottom: 91.4634%; /* 900/984 */
	}
}

/****************************
    /Artifacto Mobile Layout — artifacto.php has no get_header(), so
    #hedmobile's markup is duplicated directly into the template
    itself (same ids, so this CSS/mobile-nav.js need no changes).
    #hedsingle gets the standard hidden-behind-#hedmobile treatment
    (no owner exception here, unlike 404).

    .artifactowrap is a plain black player box with no cap/paper
    artwork, so it's a straight fixed-to-fluid width/margin
    conversion. The embedded Ruffle/Flash <iframe height="900"> needs
    the same height:0/padding-bottom aspect-ratio lock as every other
    fixed-height embed in this file — reused via the existing
    .rack-content--img wrapper (can't wrap the_content()'s own
    iframe output directly), scoped to .artifactowrap so it doesn't
    reach that class's other, <img>-based consumers. */
@media (max-width: 767px) {
	.mobile-shell .artifactowrap {
		width: 100%;
		height: auto;
		margin: 0;
		/* Extra breathing room before the footer, mobile only (tablet
		   stays flush) — background is black regardless, so the
		   negative space reads fine. 36.5854% = 40% of
		   .rack-content--img's own rendered height (91.4634%, below)
		   expressed against the SAME width reference, since percentage
		   margin always resolves against the containing block's width,
		   not this element's own height. */
		margin-bottom: 36.5854%;
	}

	/* .rack-content--img's own width/height/padding-bottom (the
	   900/984 fixed-to-fluid conversion) is shared with tablet — see
	   the merged @media(max-width:1024px) rule right after "End /404
	   Mobile Layout" above. Overrides the unscoped .artifactowrap
	   .rack-content rule's own fixed width:1045px/margin-left:13px, or
	   the box stays fixed-width and overflows. */
	.mobile-shell .artifactowrap .rack-content--img iframe {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
	}
}
/****************************
    End /Artifacto Mobile Layout
**********************************************/

/****************************
    /Main Mobile Layout — main.php, the site's actual front page
    (confirmed live: is_front_page() true, page-template-main-php in
    body_class()). Owner's spec, gathered directly: video promo → 3
    VHS episode spines → 3 vault tapes (not 10) → sidebar (its own
    existing order, minus the daily gif/flyer/bottom-cap lip) →
    footer — sidebar stacked below content, same idea as /404's own
    stacking above.

    Selectors below are plain .mobile-shell wherever the class name is
    unique to main.php (.thevault, .vhs, .tray/.creditsbutton,
    .vaultcounter/.vaultbutton, .streamingbuttons, .sidetray/.artibtn)
    or shared with 404.php but wanting the IDENTICAL treatment
    (#leftmenu, .main-columns, .sidebarbottom) — 404's own
    .error404-scoped rules carry one more class and stay more specific
    regardless of source order, so there's no real leak risk to design
    around there. Two classes ARE ancestor-scoped, not out of caution
    but because they need genuinely different NUMBERS in this context:
    .preview/.vhssm (also /vault's own archive grid, a different
    container width) via the .thevault ancestor already in the markup,
    and .albums (also /gallery's landing page, different source art)
    via the #leftmenu ancestor. .sidebargif is the one real,
    unavoidable contradiction: identical DOM path in both
    sidebar-custom.php and 404.php, but main wants it hidden while 404
    wants it visible — handled with a single :not(.error404) guard
    instead of a parallel scoping system.
**********************************************/
@media (max-width: 767px) {

	/* .mainpromo — the video's own width="710"/height="533" HTML
	   attributes still govern its rendered size until something
	   overrides them; the earlier display:block fix (see that rule,
	   outside any media query) only fixed the inline-element gap
	   below it, it never made the box itself fluid. */
	.mobile-shell .mainpromo {
		width: 100%;
		height: auto;
	}

	.mobile-shell .main-columns {
		flex-direction: column;
		gap: 0;
	}

	/* #container renders first visually (video/tapes), #leftmenu (the
	   sidebar) second — DOM order is unchanged (the sidebar is first
	   in main.php's own markup, via get_sidebar('custom') before
	   #container opens); order:-1 is the same trick /404 already uses
	   for the identical "sidebar first in the DOM, second on screen"
	   need. */
	.mobile-shell .one-column#container {
		flex: none;
		width: 100%;
		min-width: 0;
		order: -1;
	}

	.mobile-shell #leftmenu {
		width: 100%;
		margin-left: 0;
	}

	/* Covers every plain <img> sitting directly in an #leftmenu <li>
	   with no dedicated class of its own — the streaming-album cover,
	   the "now streaming" plate, and the 4 cassette-spine links.
	   display:block is needed on purpose, not just width/height — same
	   ~inline-image line-box gap already documented and fixed
	   elsewhere in this project (e.g. /music's .rackmountplacer img). */
	.mobile-shell #leftmenu li img {
		width: 100%;
		height: auto;
		display: block;
	}

	/* .sidebarmiddle — sidebarmiddle.png is a real 350x6 tiling strip
	   (confirmed via sips), no background-size at all in its shared
	   rule (see style.css, outside any media query), so it painted at
	   its native 350px width regardless of #leftmenu's own fluid
	   width. At mobile #leftmenu can be well over 350px (up to the
	   full viewport), leaving a real gap down the right edge where the
	   background never reached — confirmed live, not assumed (the
	   owner's own report: "everything flush... except this containing
	   element"). width:100% tracks #leftmenu's own fluid width;
	   height stays a fixed 6px, unchanged, so the repeat-y tiling
	   itself isn't affected, only the one tile's own width is. */
	.mobile-shell .sidebarmiddle {
		background-size: 100% 6px;
	}

	/* .tray/.creditsbutton — the >>VAULT<< button — dropped entirely
	   per the owner's ask, not made fluid like everything else on this
	   page. */
	.mobile-shell .tray {
		display: none;
	}

	/* .thevault — single column, no pairing: float:none/clear:both,
	   the same shape /vault's own mobile grid uses for the identical
	   ".preview + .vhssm sibling pair" component. */
	.mobile-shell .thevault {
		float: none;
		clear: both;
		padding: 0;
		margin: 0;
		width: 100%;
	}

	/* Keeps only the first 3 of the day's already-shuffled 10 —
	   wahnsinn-pick-trim-init.js (functions.php section 20) still
	   picks and renders 10 real DOM nodes regardless of viewport, so
	   this is a pure display cut, not a second, independent pick — the
	   owner's confirmed choice over adding a viewport-conditional
	   pick-count to the shared JS. NOT :nth-of-type(n+4) — the 3 .vhs
	   episode-spine figures come right before .thevault's own 10 in
	   the same parent, and :nth-of-type counts by TAG (both are
	   <figure>), not by class, so that selector matched (and hid) all
	   10 instead of just the last 7 — confirmed live before landing
	   this fix (0 tapes visible, not 3). The chained general-sibling
	   selector below counts only .thevault instances specifically,
	   independent of whatever non-.thevault siblings precede them. */
	.mobile-shell .thevault ~ .thevault ~ .thevault ~ .thevault {
		display: none;
	}

	.mobile-shell .thevault .preview {
		width: 100%;
		height: 0;
		padding-bottom: 75.1%; /* 263/350.2 — same box /vault's own .preview uses */
		position: relative;
		margin: 0;
	}

	.mobile-shell .thevault .preview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.mobile-shell .thevault .preview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
	}

	.mobile-shell .thevault .vhssm {
		width: 100%;
		height: 0;
		padding-bottom: 19.13%; /* 67/350.2 — same box /vault's own .vhssm uses */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		padding-left: 0;
		font-size: 6vw; /* 21/350.2, same ratio and same full-width-column shape as /vault's own mobile .vhssm */
		word-spacing: -0.29vw;
	}

	.mobile-shell .thevault .vhssm a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
		line-height: normal;
	}

	/* .vhs — the 3 episode-tape spines, single full-width column, no
	   pairing (never was paired even at desktop) — same shape and
	   technique as /episodes' own .vhsl fix. background-size was moved
	   to the shared .vhs rule (see style.css, outside any media query)
	   specifically so it can be overridden here without !important. */
	.mobile-shell .vhs {
		width: 100%;
		height: 0;
		padding-bottom: 19.128%; /* 136/711 */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		font-size: 5.9072vw; /* 42/711 */
		word-spacing: -0.1406vw; /* -1/711 */
		line-height: normal;
	}

	.mobile-shell .vhs a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/* .vaultcounter — a real 350x86 background image plus a 10px blank
	   gap below it (desktop's own height:86px + padding-bottom:10px —
	   the 10px was never part of the image). position:relative added
	   so .vaultbutton below can be absolutely positioned against this
	   box's real (padding-derived) height instead of the literal 0 a
	   percentage height would otherwise resolve against. */
	.mobile-shell .vaultcounter {
		position: relative;
		width: 100%;
		height: 0;
		padding-bottom: 24.5714%; /* 86/350 */
		background-size: 100% 100%;
		margin-bottom: 2.8571%; /* 10/350 — the original blank gap, now a margin since height:0 holds no content-box room for it */
	}

	/* .vaultbutton — was a normal-flow child offset via padding at
	   desktop; padding percentages resolve against the container's
	   WIDTH even for top/bottom (a real CSS quirk), which stopped
	   being usable once .vaultcounter went to height:0. Absolute
	   positioning instead: top/height resolve against the .vaultcounter
	   padding-box's real HEIGHT, left/width against its real WIDTH —
	   the normal rule for absolutely positioned percentages. */
	.mobile-shell .vaultbutton {
		position: absolute;
		left: 69.4286%; /* 243/350 */
		top: 50%; /* 43/86 */
		width: 18%; /* 63/350 */
		height: 33.7209%; /* 29/86 */
		padding: 0;
	}

	/* vault-button.png is a real 189x29 3-frame sprite (confirmed via
	   sips) — background-size:300%/position 0%,50%,100% is the
	   standard fluid-sprite conversion (same technique this file
	   already uses for other sprite buttons). Frame order re-derived
	   from the sprite's own pixel math, since the desktop rule's mixed
	   positive/negative px offsets (-63px, 0, 63px on a 63px-wide box)
	   only worked via background-repeat's default tiling wraparound:
	   hover=frame0, link/default=frame1, active=frame2. */
	.mobile-shell .vaultbutton a:link,
	.mobile-shell .vaultbutton a:visited,
	.mobile-shell .vaultbutton a:hover,
	.mobile-shell .vaultbutton a:active {
		width: 100%;
		height: 100%;
		background-repeat: no-repeat;
		background-size: 300% 100%;
	}
	.mobile-shell .vaultbutton a:link,
	.mobile-shell .vaultbutton a:visited {
		background-position: 50% 0;
	}
	.mobile-shell .vaultbutton a:hover {
		background-position: 0 0;
	}
	.mobile-shell .vaultbutton a:active {
		background-position: 100% 0;
	}

	.mobile-shell .streamingbuttons {
		width: 100%;
		margin-left: 0;
	}

	.mobile-shell .streamingbuttons img {
		width: 33.314%; /* 114.6/344 — unchanged ratio, still 3-per-row */
		height: auto;
	}

	/* #leftmenu .albums — NOT bare .mobile-shell .albums, see the
	   /gallery Mobile Layout block's own rescope comment further up:
	   /gallery's own .albums (inside .albumgallery) is a different,
	   much larger image with its own tuned negative-margin/clip-path
	   overrides that don't apply to these small sidebar icons. */
	.mobile-shell #leftmenu .albums {
		display: block;
		width: 100%;
	}

	.mobile-shell #leftmenu .albums img {
		width: 100%;
		height: auto;
	}

	/* .sidetray/.artibtn — the Artifacto button tray, same shape as
	   .vaultcounter/.vaultbutton above (a real background-image tray
	   plus a normal-flow, offset sprite button on top). */
	.mobile-shell .sidetray {
		position: relative;
		width: 100%;
		height: 0;
		padding-bottom: 22.2857%; /* 78/350 */
		background-size: 100% 100%;
	}

	.mobile-shell .artibtn {
		position: absolute;
		left: 40%; /* 140/350 */
		top: 2.5641%; /* 2/78 */
		width: 20%; /* 70/350 */
		height: 94.8718%; /* 74/78 */
		padding: 0;
	}

	/* artibtn.png is a real 210x74 3-frame sprite (confirmed via
	   sips), same technique as .vaultbutton above. Frame order
	   re-derived the same way: active=frame0, link/default=frame1,
	   hover=frame2. */
	.mobile-shell .artibtn a:link,
	.mobile-shell .artibtn a:visited,
	.mobile-shell .artibtn a:hover,
	.mobile-shell .artibtn a:active {
		width: 100%;
		height: 100%;
		background-repeat: no-repeat;
		background-size: 300% 100%;
	}
	.mobile-shell .artibtn a:link,
	.mobile-shell .artibtn a:visited {
		background-position: 50% 0;
	}
	.mobile-shell .artibtn a:hover {
		background-position: 100% 0;
	}
	.mobile-shell .artibtn a:active {
		background-position: 0 0;
	}

	/* Dropped entirely per the owner's ask. .sidebargif needs the
	   :not(.error404) guard since 404.php shares this exact DOM path
	   and wants it VISIBLE, not hidden (see the block comment above);
	   .sidebarflyer is main-only so no guard is needed; .sidebarbottom
	   is already hidden for 404 via its own .error404-scoped copy
	   further up this file, so a bare rule here is redundant for 404
	   but harmless. Once these three are hidden, .sidetray/.artibtn
	   (the Artifacto button) ends up last before the footer. */
	.mobile-shell:not(.error404) .sidebargif {
		display: none;
	}
	.mobile-shell .sidebarflyer {
		display: none;
	}
	.mobile-shell .sidebarbottom {
		display: none;
	}

	/* Same root cause as #footer .cg-footer's own "too blurry at small
	   sizes" fix (see "Base CG Effect" above) — flagged there as
	   untouched at the time. .cg-sidebar's own filter:blur(1.4px) is
	   flat, unparameterized. Unlike the footer/header-label, this
	   element's font-size is a fixed 24px at every breakpoint (not
	   vw-scaled), so this isn't a "gets worse at smaller widths" bug —
	   the owner just found the existing flat 1.4px too heavy here,
	   period. --cg-blur:0.03em resolves to 0.72px at this element's
	   24px, well under the current 1.4px. First-pass estimate, not yet
	   owner-confirmed live — revisit if it needs to be sharper/softer.
	   sidebar-custom.php is shared with 404.php, which also wants this
	   fix (no reason for the two pages to render this differently, so
	   no .error404 guard here unlike .sidebargif above). Owner's live
	   follow-up on the header label's own 0.03em (see
	   #vaultHeaderCategoryLabel.cg above) asked to split the difference
	   between the old flat 1.4px and 0.03em's result — same math
	   applied here: old ratio 1.4/24=0.0583, new 0.03, average
	   0.0442 ≈ 0.045em, resolving to 1.08px (this element's font-size
	   is a fixed 24px everywhere, so unlike the label there's no
	   separate 767px-vs-375px anchor question). */
	.mobile-shell .cg-sidebar {
		--cg-blur: 0.045em;
	}
}
/****************************
    End /Main Mobile Layout
**********************************************/

/****************************
    /vault + /blog Tablet Layout (768px-1024px — see Vault Work/
    HANDOVER.md for the full rollout history)

    The site's pre-existing #topmenu/#mobiletopmenu swap at
    max-width:1024px was never actually responsive — just a
    fixed-1100px alternate skin, built for browsers that auto-shrink
    the whole desktop layout to fit with no viewport tag. /vault and
    /blog now carry a real viewport tag, so this range needs a
    genuinely fluid layout instead, including a fluid nav bar.

    Shared, page-level rules (#wrapper, #footer, #hed, the
    #mobiletopmenu nav bar) use .mobile-shell — none of it is actually
    vault-specific. Genuinely category-specific archive-grid rules
    stay on their real .category-{slug} class: .vault3/.preview/
    .vhssm below are .category-vault only; .micro/.cart get their own
    .category-blog block (already 2 columns at desktop, so this is a
    fixed-to-fluid conversion only, not a column-count change).
****************************/

@media (min-width: 768px) and (max-width: 1024px) {

	.mobile-shell #wrapper {
		position: relative;
		width: 100%;
		background-image: none;
	}

	/* rackbars.png's edge art (44px each side — same image and same
	   pixel breakdown as the /vault Load More section's tray fix
	   below: a 12px frame-border strip, a 1px bevel line, then a 31px
	   rack-mount bar with a bolt hole) is normally just #wrapper's own
	   background-image, which only works because #wrapper is a fixed
	   1100px box the image is drawn against 1:1. Painting the FULL
	   1100px image as a fluid #wrapper's background again would be
	   wrong in a new way: the image also has two more bar-pairs in
	   the middle (x=331-406, x=693-768), meant to land in the seam
	   between #leftmenu and #container on pages that HAVE a sidebar —
	   /vault doesn't. At a FIXED 1100px width those always fall
	   outside the visible content anyway; at a FLUID width they'd
	   land somewhere inside the 2-column grid instead, wherever the
	   container's current width happens to put them — not aligned
	   with anything, a stray bar floating over card content at some
	   viewport widths and not others.

	   Fix: two narrow (44px) pseudo-elements, one pinned to each
	   edge, each showing only its OWN 44px slice of the unscaled
	   image via background-position:left/right — physically too
	   narrow to ever show the middle bar-pairs at all, at any
	   container width in this range. z-index:-1 keeps them behind all
	   real content, matching how a plain background-image always
	   paints beneath everything else in its own box; #wrapper needed
	   position:relative added above so these position:absolute
	   children resolve against it, not the viewport. */
	.mobile-shell #wrapper::before,
	.mobile-shell #wrapper::after {
		content: '';
		position: absolute;
		top: 0;
		width: 44px;
		height: 100%;
		background-image: url('/assets/images/structure/rackbars.png');
		background-repeat: repeat-y;
		z-index: -1;
		pointer-events: none;
	}

	.mobile-shell #wrapper::before {
		left: 0;
		background-position: left top;
	}

	.mobile-shell #wrapper::after {
		right: 0;
		background-position: right top;
	}

	/* 12px inset each side, not flush 100% — same reasoning and same
	   number as the Load More tray's own desktop fix (see that
	   section below): rackbars.png's edge art has a 12px frame-border
	   strip that's meant to stay visible, then a 32px rack-mount
	   bar+bolt-hole that's fine to sit under opaque content. A flush
	   100%-wide #content (like the first pass at this breakpoint
	   shipped with) sits directly on top of the #wrapper::before/
	   ::after pseudo-elements below, hiding the frame border
	   completely — not just the bar+hole this time, all 44px of it,
	   since unlike desktop's grid (which has small per-card gutters
	   exposing a sliver naturally) this grid and the nav bar below
	   are both deliberately flush edge-to-edge with zero internal
	   gutter. #mobiletopmenu gets the identical inset, for the same
	   reason — see that rule below. */
	.mobile-shell .single-30mom #content {
		width: calc(100% - 24px);
		margin: 0 auto;
	}

	/* Single vault posts' rack-frame content (video → credits paper →
	   prev/next tray), catsingle.php's vault/episodes branch — same
	   fluid-background techniques as the rest of this Tablet Layout
	   section (#hed/#hedsingle, #footer below), but reusing the
	   DESKTOP rack art (fullrack.png, fullrack-topper.png,
	   fullrack-bottom.png, fullrack-label.png, full-tray.gif) rather
	   than the dedicated mobile-rack-topper/label/bottom.png and
	   mobile-tray.gif assets used ≤767px above — confirmed with the
	   owner that tablet keeps the
	   desktop look here, fluid instead of a second, separate
	   mobile-tuned redesign. Every percentage below is that element's
	   own already-correct desktop pixel geometry (unchanged from the
	   unscoped rules elsewhere in this file) divided by fullrack.png's
	   native 1074px width (or, for vertical values, the relevant
	   asset's own native height) — not re-measured from scratch, since
	   the desktop numbers are already proven correct and this is
	   purely a fixed-to-fluid conversion of them, the same thing every
	   other element in this section already does. */

	.mobile-shell .rack-screen {
		width: 100%;
		margin: 0 auto;
		background-size: 100% auto;
	}

	.mobile-shell .rack-screen__inner {
		width: 60.0559%; /* 645/1074 */
		margin-left: 20.0186%; /* 215/1074 */
	}

	.mobile-shell .rack-cap--narrow {
		width: 100%;
		margin: 0 auto;
	}

	.mobile-shell .rack-cap--top.rack-cap--narrow {
		background-size: 100% 100%;
		height: 0;
		padding-bottom: 2.7003%; /* 29/1074 */
	}

	.mobile-shell .rack-cap--bottom.rack-cap--narrow {
		background-size: 100% 100%;
		height: 0;
		padding-bottom: 4.2831%; /* 46/1074 */
	}

	.mobile-shell .rack-paper--narrow {
		background-size: 100% auto;
		width: 100%;
		margin: 0 auto;
	}

	.mobile-shell .rack-paper--narrow .rack-content {
		width: 58.2867%; /* 626/1074 */
		margin-left: 20.7635%; /* 223/1074 */
	}

	/* /blog singles' WIDE rack family (catsingle.php's blog/merch
	   branch) — unlike the mobile block above, this does NOT reuse the
	   narrow family's rules: at tablet width each family keeps its OWN
	   desktop art made fluid (confirmed with the owner — same call
	   already made for narrow's own tablet treatment), so this needs
	   its own percentages derived from the wide art's native
	   dimensions (fullrack-topperwide.png/fullrack-bottomwide.png/
	   fullrack-paperwide.png, 1074px reference — same file the
	   unscoped desktop .rack-cap--wide/.rack-paper--wide rules already
	   use, see further up this file) rather than the narrow art's. */
	.mobile-shell .rack-cap--wide {
		width: 100%;
		margin: 0 auto;
	}

	.mobile-shell .rack-cap--top.rack-cap--wide {
		background-size: 100% 100%;
		height: 0;
		padding-bottom: 4.5623%; /* 49/1074 */
	}

	.mobile-shell .rack-cap--bottom.rack-cap--wide {
		background-size: 100% 100%;
		height: 0;
		padding-bottom: 7.1704%; /* 77/1074 */
	}

	.mobile-shell .rack-paper--wide {
		background-size: 100% auto;
		width: 100%;
		margin: 0 auto;
	}

	/* Desktop's .rack-paper--wide .rack-content is width:1045px;
	   margin-left:13px inside the 1074px paper (see the unscoped rule
	   further up this file) — converted directly, same "px ÷ native
	   reference width" method as every other fluid conversion here. */
	.mobile-shell .rack-paper--wide .rack-content {
		width: 97.3184%; /* 1045/1074 */
		margin-left: 1.2104%; /* 13/1074 */
	}

	/* .rack-content--img (single /photos posts) — same fix and same
	   reasoning as the mobile block's own copy above (~line 4585):
	   the unscoped desktop rule hardcodes width:1045px, matching the
	   fixed .rack-content column it used to sit in exactly; now that
	   the column above is fluid at this breakpoint too, the image
	   needs to track it. Scoped to .mobile-shell rather than unscoped
	   since this class is also used by artifacto.php's player box,
	   a separate page this join has no business touching. */
	.mobile-shell .rack-content--img img {
		width: 100%;
	}

	/* .rack-content--text img — /contact's own fix, same reasoning as
	   the /Contact Mobile Layout block's own copy above: defensive
	   img clamp for a real spinning-smiley GIF in the page's content,
	   .mobile-shell-scoped rather than unscoped since .rack-content--
	   text is shared by five other, out-of-scope text.php pages.
	   Needs its own copy here since this is a separate media query. */
	.mobile-shell .rack-content--text img {
		max-width: 100%;
		height: auto;
	}

	/* .blogtext's fixed margin-left:35px, same fix/reasoning as the
	   mobile block above — needs its own copy since this is a separate
	   media query. */
	.mobile-shell .rack-content--blog .blogtext {
		margin-left: 3.3493%;
	}

	/* Same overflow fix as the mobile block above — .notepaper (a
	   sitewide fixed-500px testimonial-quote component, not specific
	   to this rack area) is wider than .rack-content at this
	   breakpoint's own narrow end (768px puts .rack-content at
	   roughly 448px, well under 500px) even though it fits fine at
	   the range's wider end (1024px, roughly 597px) — needs its own
	   copy of the fix here since this is a separate media query. */
	.mobile-shell .rack-content--credits .notepaper,
	.mobile-shell .rack-content--blog .notepaper {
		width: 100%;
		max-width: 31.25rem;
	}

	/* .widestreamingbuttons — same fix/reasoning as the mobile block
	   above, needs its own copy since this is a separate media query.
	   .rack-content--blog is still fluid but comfortably wider here
	   (roughly 700-1000px) than mobile's 320-767px, but the fixed
	   1000px .widestreamingbuttons container still doesn't fit at this
	   range's own narrow 768px end (#content's shared 24px tablet
	   inset alone puts it under 1000px) — same 30% per image as
	   mobile works fine at any width in this range too, no extra
	   tablet-inset correction factor needed (this is plain percentage-
	   of-container image sizing, not vw-based text, so it isn't
	   sensitive to the range's own narrow-end proportional inset the
	   way /blog's archive excerpt text was). */
	.mobile-shell .rack-content--blog .widestreamingbuttons {
		width: 100%;
		margin-left: 0;
	}

	.mobile-shell .rack-content--blog .widestreamingbuttons img {
		width: 30%;
	}

	/* #fulltray: desktop's version positions the finger buttons via
	   #fulltray's own padding-left:184px plus each button's own
	   margin-left (100px/504px) — all fixed px, meaningless once the
	   tray itself is fluid, so this switches to the same
	   position:relative + percentage left/bottom technique already
	   used for the mobile tray above, with the buttons' left offsets
	   converted directly from those same proven desktop px values
	   (184+100=284, 184+504=688) rather than re-measuring full-tray.gif
	   from scratch. bottom:0 (not a measured top) for the same reason
	   documented in the mobile block above: it's a simpler, more
	   robust anchor than chasing the icon's exact pixel bounds, and
	   matches how desktop's own padding-top:8px on a 71px button
	   inside the real 79px-tall bar already works out to flush-bottom
	   in practice. */
	.mobile-shell #fulltray {
		background-size: 100% 100%;
		width: 100%;
		height: 0;
		padding-bottom: 7.3557%; /* 79/1074 */
		padding-left: 0;
		margin: 0 auto;
		position: relative;
	}

	.mobile-shell .fingerbuttonleft,
	.mobile-shell .fingerbuttonright {
		position: absolute;
		padding-top: 0;
		margin-left: 0;
		width: 8.9385%; /* 96/1074 */
		height: 89.8734%; /* 71/79 */
		bottom: 0;
	}

	.mobile-shell .fingerbuttonleft {
		left: 26.4432%; /* 284/1074 */
	}

	.mobile-shell .fingerbuttonright {
		left: 64.0596%; /* 688/1074 */
	}

	/* Longhand only, matching the mobile block's own reasoning above —
	   background-image/repeat are unchanged from the desktop rule
	   (same fingerbuttonleft.png/fingerbuttonright.png, no swap here),
	   only background-size/position and the box's own width/height
	   need overriding for the fluid sprite math. */
	.mobile-shell .fingerbuttonleft a:link,
	.mobile-shell .fingerbuttonleft a:visited {
		background-image: url('/assets/images/structure/fingerbuttonleft.png');
		background-repeat: no-repeat;
		background-size: 300% 100%;
		background-position: 0% 0;
		width: 100%;
		height: 100%;
		display: block;
	}

	.mobile-shell .fingerbuttonleft a:hover {
		background-position: 50% 0;
	}

	.mobile-shell .fingerbuttonleft a:active {
		background-position: 100% 0;
	}

	.mobile-shell .fingerbuttonright a:link,
	.mobile-shell .fingerbuttonright a:visited {
		background-image: url('/assets/images/structure/fingerbuttonright.png');
		background-repeat: no-repeat;
		background-size: 300% 100%;
		background-position: 0% 0;
		width: 100%;
		height: 100%;
		display: block;
	}

	.mobile-shell .fingerbuttonright a:hover {
		background-position: 50% 0;
	}

	.mobile-shell .fingerbuttonright a:active {
		background-position: 100% 0;
	}

	/* NOT background-size:cover — footer.png is 1100x46 native, exactly
	   matching #footer's own unscoped height:46px 1:1 on desktop (no
	   scaling occurs there at all). `cover`'s own scale factor is
	   max(box_width/1100, box_height/46) — since height already
	   matches exactly, that's max(<1, 1) = 1, so `cover` renders the
	   image at its full native 1100px width regardless of how much
	   narrower the actual (fluid, ≤1024px here) box is, then centers
	   and crops the overflow — chopping the end-cap art off both
	   sides, worse the narrower the viewport gets. Confirmed by the
	   math, not just observed: this necessarily fires at every width
	   in this range, and likely on mobile too (same `cover` approach
	   there — not yet fixed, flagged, not touched here since it's
	   Phase 1's already-shipped code and out of scope for this pass).

	   Fix: the same padding-bottom aspect-ratio technique as every
	   other fluid image box in this project (46/1100 = 4.1818%),
	   scaling the whole bar — end caps included — proportionally with
	   width instead of cropping or stretching it. The real text
	   content (footer.php's .cg.cg-footer div) needs the matching
	   position:absolute + flex treatment every other height:0 box in
	   this file uses, since padding-bottom leaves no real content
	   height for normal text flow to center within. Unlike
	   #vaultHeaderCategoryLabel's own version of this same flex
	   switch, no matching .cg::before fix is needed here — footer.php
	   never sets a data-text attribute, so .cg::before's
	   content:attr(data-text) is just empty, nothing to misalign. */
	.mobile-shell #footer {
		width: 100%;
		height: 0;
		padding-bottom: 4.1818%;
		background-size: 100% 100%;
		position: relative;
	}

	/* font-size was missing here entirely — the bar itself (above)
	   was already made fluid, but the copyright text stayed a fixed
	   16px throughout the whole range, unlike everything else in this
	   section. 1.4545vw = 16/1100, the same "native px ÷ native
	   reference width" derivation every other vw value in this file
	   uses. The centering mechanism itself lives once, unscoped, on
	   the base .cg-footer rule — this copy only needs font-size. */
	.mobile-shell #footer .cg-footer {
		font-size: 1.4545vw;
	}

	/* #hed (the desktop TV-wall banner, header-mobile.php) is the
	   OTHER fixed-1100px element on this page besides #wrapper itself
	   — easy to miss since it's not mentioned anywhere else in this
	   section, but its own hardcoded width:1100px (see the shared,
	   unscoped #hed rule) forces the same horizontal-scroll problem
	   all over again if left alone, even with everything above fixed.
	   No mobile-style redesign here (that's #hedmobile, still
	   ≤767px-only) — just the same banner GIF, scaled fluid instead
	   of shown at native 1100x461 size, keeping the tablet range
	   closer to "responsive desktop" than "simplified mobile", which
	   matches 2 columns being a scaled-down 3 rather than a stacked
	   1. #hedsingle (single vault posts' own 1100x174 desktop banner,
	   reused as-is from header-single.php) gets the identical fluid
	   treatment for the identical reason — it's the other fixed-width
	   banner a single vault post can render instead of #hed. */
	.mobile-shell #hed,
	.mobile-shell #hedsingle {
		width: 100%;
		height: auto;
	}

	.mobile-shell #hed img,
	.mobile-shell #hedsingle img {
		display: block;
		width: 100%;
		height: auto;
	}

	/* ===== Nav bar: same #mobiletopmenu/#mobilenavlisttop bar the
	   site already shows at this width, made genuinely fluid instead
	   of left at its fixed 1100px/200px-per-button sizing. Still the
	   same 10 items, same mobilebutton.png/epbutton.png art, same
	   rest/hover/current behavior — only the sizing mechanism
	   changes, from fixed px + float-wrap to a real grid. ===== */

	/* 5 columns x 2 rows, matching the item count (10) and the
	   arrangement the fixed version already wraps into today via
	   float (confirmed by measuring it directly: 5 per row at
	   1100px ÷ ~219px-per-button). Unlike the hamburger drawer's own
	   3x3 grid, nothing here is hidden and no JS-measured row height
	   is needed — this is normal in-flow content, not an overlay
	   competing with a sticky header for a fixed remaining-viewport
	   height, so each row can just size to its own content. */
	/* height:0 + padding-bottom:19.0909% (210/1100, the panel's native
	   ratio) keeps the real mobiletopmenu.png art fluid, rather than
	   background-image:none — dropping the art would lose its baked-in
	   column gutter and bottom bevel ("lip") that every other page
	   still on the old fixed #mobiletopmenu (e.g. /music) shows.
	   width:100%/margin:0 — no 24px inset here: the art's own baked-in
	   bezel must land flush against #wrapper's own rack-frame edge to
	   read as one continuous border, not a doubled one. The button
	   grid below is unaffected since its own insets are percentages of
	   this box, not of #wrapper. */
	.mobile-shell #mobiletopmenu {
		width: 100%;
		margin: 0;
		height: 0;
		padding-bottom: 19.0909%;
		background-image: url('/assets/images/structure/mobiletopmenu.png');
		background-size: 100% 100%;
		background-repeat: no-repeat;
		position: relative;
	}

	/* Absolutely positioned within the panel now (not normal flow),
	   inset to exactly where the buttons sit inside mobiletopmenu.png —
	   measured directly off the old fixed-px /music rendering (13px
	   left, 11px right, 0 top, 10px bottom, out of the panel's native
	   1100x210): left/right insets are % of width, top/bottom are % of
	   height, per how absolutely-positioned offsets resolve. column-gap
	   is a % of #mobilenavlisttop's OWN (already-inset) width, not the
	   panel's — 19/1076, not 19/1100 — since that's what CSS gap
	   percentages resolve against; using the panel-relative number here
	   would leave the columns fractionally too wide and drift the grid
	   out of alignment with the art at wider tablet widths. */
	.mobile-shell #mobilenavlisttop {
		position: absolute;
		top: 0;
		left: 1.1818%;
		right: 1%;
		bottom: 4.7619%;
		/* The unscoped base rule (search "#mobilenavlisttop{" above)
		   sets a fixed width:1100px/height:100px — same ID-beats-class
		   specificity trap as everywhere else in this section, but this
		   time it's not a losing property fight, it's an over-constrained
		   one: with left+width+right (or top+height+bottom) all
		   non-auto, the explicit width/height wins and the opposite
		   inset (right/bottom) gets silently ignored, which is exactly
		   what happened here the first time this was written — the bar
		   rendered at its old fixed 1100px width even with left/right
		   set. width/height:auto here is load-bearing, not redundant. */
		width: auto;
		height: auto;
		display: grid;
		grid-template-columns: repeat(5, 1fr);
		column-gap: 1.7658%;
		row-gap: 0;
		margin: 0;
	}

	/* #mobilenavlisttop prefixed onto every one of these (not just
	   .mobile-shell) is load-bearing, not decorative — same
	   specificity trap already documented in the "Button textures"
	   section below for the drawer's own version of this fix: the
	   unscoped base rule `#mobilenavlisttop li, #mobilenavlisttop li
	   a {height:100px}` is an ID selector, which beats a plain class
	   selector regardless of source order. Adding the #mobilenavlisttop
	   ID here raises this rule to ID+class specificity so it actually
	   wins.

	   height:0 + padding-bottom:50% (the classic percentage-
	   aspect-ratio technique, not the `aspect-ratio` property — see
	   the long comment on the drawer's own button rules below for why
	   this project avoids that property) matches mobilebutton.png's
	   native 200:100 (2:1) per-frame ratio, resolved against each
	   button's own fluid width (1fr = 1/5 of the container). */
	.mobile-shell #mobilenavlisttop .mobilebutton,
	.mobile-shell #mobilenavlisttop .currentmobilebutton,
	.mobile-shell #mobilenavlisttop .epmobilebutton,
	.mobile-shell #mobilenavlisttop .currentepmobilebutton {
		float: none;
		width: 100%;
		height: 0;
		padding-bottom: 50%;
		margin: 0;
		position: relative;
		background-repeat: no-repeat;
		background-size: 300% 100%;
	}

	/* Same reasoning as the drawer's own version of this rule: the
	   unscoped `#mobilenavlisttop li a {display:block; height:100px;
	   line-height:100px}` base rule is ID-based and beats a plain
	   class selector outright, so text position needs the same
	   #mobilenavlisttop-prefixed override, then absolute+flex instead
	   of the old fixed-line-height centering trick (this box's real
	   height is now fluid, not a fixed px line-height could reliably
	   match). */
	.mobile-shell #mobilenavlisttop .mobilebutton a,
	.mobile-shell #mobilenavlisttop .currentmobilebutton a,
	.mobile-shell #mobilenavlisttop .epmobilebutton a,
	.mobile-shell #mobilenavlisttop .currentepmobilebutton a {
		position: absolute;
		inset: 0;
		height: auto;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/* background-position math (0%/-50%/-100%) is derived purely from
	   frame count (mobilebutton.png/epbutton.png are both 3-equal-
	   frame strips, rest/hover/current left to right — same structure
	   as thin-button.png/thin-epbutton.png below, just different
	   pixel dimensions), not pixel dimensions, so the same percentages
	   apply unchanged. epbutton.png's "current" state reuses the
	   hover frame (50%) rather than getting its own third frame,
	   matching its unscoped desktop behavior exactly (confirmed
	   directly against the desktop .epbutton/.currentepbutton rules
	   above) — not a mistake, mobilebutton.png and epbutton.png
	   genuinely differ here.

	   Percentages are POSITIVE (0%/50%/100%), not negative — verified
	   directly in the browser, not assumed: at background-size:300%
	   100%, the used-value formula is offset = percentage × (box_width
	   - image_width), and since the image is wider than the box here,
	   (box_width - image_width) is already negative, so a NEGATIVE
	   percentage flips it positive — pushing the image the wrong
	   direction entirely, off into blank space before frame 1 rather
	   than onto frames 2/3. Caught because .currentmobilebutton
	   rendered fully blank/black at -100% before this fix. */
	.mobile-shell .mobilebutton {
		background-image: url('/assets/images/structure/mobilebutton.png');
		background-position: 0% 0;
	}

	.mobile-shell .currentmobilebutton {
		background-image: url('/assets/images/structure/mobilebutton.png');
		background-position: 100% 0;
	}

	.mobile-shell .epmobilebutton {
		background-image: url('/assets/images/structure/epbutton.png');
		background-position: 0% 0;
	}

	.mobile-shell .currentepmobilebutton {
		background-image: url('/assets/images/structure/epbutton.png');
		background-position: 50% 0;
	}

	/* The a:hover/a:active rules only work at fluid scale because the
	   original CSS sets them via the `background` SHORTHAND, which
	   implicitly resets background-size to its initial value (auto)
	   for anything the shorthand doesn't mention — re-declaring
	   background-size here (a longhand) is what makes it win over
	   that reset regardless of which rule set background-image last;
	   longhand-vs-shorthand doesn't affect the cascade, only which
	   rule wins for that specific property does. */
	.mobile-shell .mobilebutton a:hover,
	.mobile-shell .mobilebutton a:active,
	.mobile-shell .currentmobilebutton a:hover,
	.mobile-shell .currentmobilebutton a:active,
	.mobile-shell .epmobilebutton a:hover,
	.mobile-shell .epmobilebutton a:active,
	.mobile-shell .currentepmobilebutton a:hover,
	.mobile-shell .currentepmobilebutton a:active {
		background-size: 300% 100%;
		background-position: 50% 0;
	}

	/* Text sized off each button's own fluid width, matching the
	   original 32px-at-200px-wide (0.16) ratio. This was 3.2vw
	   (0.16 x 20%) back when the buttons were a naive 1/5 grid split
	   with no gap; now that the panel/lip fix above gives them their
	   real ~18.18% width (200/1100, same as the old fixed design, once
	   column-gap and the panel's own inset are accounted for — see the
	   #mobiletopmenu/#mobilenavlisttop comments above), 3.2vw is sized
	   for a button ~10% wider than what's actually there, which is what
	   let EPISODES/GALLERY start overflowing their buttons.

	   The exact ratio match (0.16 x 18.18% = 2.909vw) measures fine in
	   this project's own Chromium tooling — real text-rendered width via
	   Range.getBoundingClientRect(), not just box scrollWidth — but only
	   with ~5% margin on "Episodes" at this range's own 768px floor
	   (the tightest point, same reason it always is elsewhere in this
	   file). That's the identical shape of fragile, near-zero-margin fit
	   that broke on real Safari font-shaping for /blog's excerpt text
	   and needed its own 0.92 safety factor (see "/blog Mobile Layout"
	   in the handover) — so the same kind of factor is applied here
	   up front rather than waiting for another live report: 2.909vw x
	   0.95 = 2.764vw. */
	.mobile-shell #mobilenavlisttop .mobilebutton,
	.mobile-shell #mobilenavlisttop .currentmobilebutton,
	.mobile-shell #mobilenavlisttop .epmobilebutton,
	.mobile-shell #mobilenavlisttop .currentepmobilebutton,
	.mobile-shell #mobilenavlisttop .mobilebutton a,
	.mobile-shell #mobilenavlisttop .currentmobilebutton a,
	.mobile-shell #mobilenavlisttop .epmobilebutton a,
	.mobile-shell #mobilenavlisttop .currentepmobilebutton a {
		font-size: 2.764vw;
	}

	/* ===== /vault archive grid: 2 columns instead of desktop's 3 or
	   mobile's 1, filling the viewport edge to edge (zero gutter,
	   matching the mobile grid's own "flush, touching" precedent —
	   see the /vault Mobile Layout section above — extended from 1
	   column to 2 rather than reintroducing desktop's 12.5px gutter
	   here). Exactly 2 per row via plain float-wrap at width:50%,
	   same underlying mechanism as desktop's 3-per-row (no clear
	   needed either way — see the desktop .vault3 rule's own
	   comment). ===== */
	.category-vault .vault3 {
		float: left;
		clear: none;
		padding: 0;
		margin: 0;
		width: 50%;
	}

	/* Same padding-bottom aspect-ratio technique as the mobile grid
	   (75.1% = 263/350.2, the .preview box's real desktop ratio),
	   just resolved against a 50%-of-container width instead of
	   100%. */
	.category-vault .preview {
		width: 100%;
		height: 0;
		padding-bottom: 75.1%;
		position: relative;
		margin: 0;
	}

	.category-vault .preview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.category-vault .preview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
	}

	/* Same 19.13% (67/350.2) ratio as the mobile grid. font-size/
	   word-spacing are half the mobile block's own 6vw/-0.29vw,
	   matching this box being roughly half the width (2 columns
	   instead of 1) rather than the full viewport. */
	.category-vault .vhssm {
		width: 100%;
		height: 0;
		padding-bottom: 19.13%;
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		padding-left: 0;
		font-size: 3vw;
		word-spacing: -0.145vw;
	}

	.category-vault .vhssm a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
		line-height: normal;
	}

	/* ===== /blog archive grid: 2 columns, same call as /vault's above,
	   but /blog's desktop grid is ALREADY 2 columns (.micro is
	   float:left/532px-wide, and two of those plus the 12.5px gutter
	   already fill the desktop content width) — so unlike /vault's
	   3-down-to-2, this isn't a column-count change at all, just the
	   same fixed-1100px -> fluid conversion every other box in this
	   section gets. Zero gutter (clear:none, margin:0), matching
	   /vault's own tablet grid immediately above rather than keeping
	   desktop's 12.5px margin-left. .cart's internal geometry (the
	   .cartspine/excerpt split) is unchanged from the /blog Mobile
	   Layout section's own measured percentages — those are all
	   relative to .cart's own box, so they hold at any box width;
	   only the vw-based font-sizes/word-spacing (relative to the full
	   viewport, not the box) need halving, same reasoning as /vault's
	   .vhssm above. ===== */
	.category-blog .micro {
		float: left;
		clear: none;
		margin: 0;
		width: 50%;
	}

	.category-blog .cart {
		width: 100%;
		height: 0;
		padding-bottom: 25.94%; /* 138/532, same ratio as mobile - unchanged by box width */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
	}

	.category-blog .cart a {
		position: absolute;
		left: 0;
		right: 0;
		display: flex;
		justify-content: center;
		padding: 0;
	}

	/* Font-size/word-spacing/letter-spacing below are scaled by
	   0.474609375, NOT a naive 0.5 (half), even though `.micro` is
	   width:50% of #content. That 50% is 50% of #content, not of the
	   viewport these vw units are actually relative to — and #content
	   is itself `calc(100% - 24px)` of the viewport at this breakpoint
	   (the 12px-per-side rack-bar inset, see "Tablet Layout" above),
	   so .cart's real width is measurably ~47.46% of the viewport at
	   this range's own 768px floor (confirmed via
	   getBoundingClientRect(), not assumed: 364.5/768), not 50%.
	   Using the naive half (0.5, i.e. 2.25vw/1.3vw) put every one of
	   these three properties about 4-5% too large relative to the
	   box's real width — nowhere near enough to be visually obvious,
	   but exactly enough to push a handful of real excerpts (measured
	   via Range.getClientRects() line-counting, e.g. the "Ethan" and
	   "Berkley PATV" posts) one word past their desktop-equivalent
	   2-line wrap, into a 3rd. 0.474609375 is this breakpoint's own
	   floor (768px) rather than its 1024px ceiling, deliberately: the
	   fixed 24px inset is a larger fraction of a narrower viewport, so
	   768px is the tightest real case in this range — if text fits
	   here, it fits everywhere else in 768-1024px too, only with more
	   room to spare as the viewport (and #content along with it) grows
	   wider. */
	.category-blog .cartspine {
		top: 0;
		height: 50%; /* 69/138 */
		align-items: flex-end;
		font-size: 2.14vw; /* 4.5 * 0.474609375, not a naive half - see comment above */
		word-spacing: -0.09vw; /* -0.19 * 0.474609375 */
		letter-spacing: 0.018vw; /* 0.038 * 0.474609375 */
	}

	.category-blog .cart a:not(.cartspine) {
		top: 50%; /* 69/138 */
		height: 13.77%; /* 19/138 */
		align-items: flex-start;
	}

	/* Same word-spacing/letter-spacing fix as the mobile block above
	   (see that rule's own comment for the root cause: `.cart p`
	   otherwise inherits two fixed, non-scaling values — the desktop
	   `.cart` rule's -1px word-spacing, and the site-wide base `p`
	   rule's 0.2px letter-spacing). Scaled by 0.474609375 here, not a
	   naive half — see `.cartspine`'s own comment just above for why. */
	.category-blog .cart p {
		width: 100%;
		padding: 0 6.58%; /* 35/532, relative to .cart's own width - unchanged by box width */
		margin: 0;
		font-size: 1.23vw; /* 2.6 * 0.474609375, not a naive half - see .cartspine's comment above */
		word-spacing: -0.09vw; /* -0.19 * 0.474609375 */
		letter-spacing: 0.018vw; /* 0.038 * 0.474609375 */
		line-height: normal;
		text-align: center;
		overflow-wrap: break-word; /* same narrow safety net as the mobile block above - see that rule's own comment for exactly what this does and doesn't do */
	}

	/* ===== /episodes archive grid: same single-full-width-item shape as
	   the mobile block (see "/episodes Mobile Layout" above), same
	   values, except font-size/word-spacing get a 0.96875 correction
	   factor the mobile block doesn't need. Reason: these are vw-based
	   (relative to the viewport), but .single-30mom #content is
	   calc(100% - 24px) at this breakpoint, not 100%, unlike mobile's
	   flush #content — so a bare 5.77vw/-0.093vw would render very
	   slightly oversized relative to the actual (narrower) box, same
	   category of bug /blog's own 0.474609375 tablet correction fixed
	   above, just simpler here since .epcon/.vhsl stays 100%-of-
	   container (no 50%-of-container halving on top of it). 0.96875 =
	   (768-24)/768, anchored to this range's own 768px floor since the
	   fixed 24px inset is proportionally largest there — same reasoning
	   as /blog's own floor-anchoring just above. ===== */
	.category-episodes .epcon {
		float: none;
		clear: both;
		margin: 0;
		width: 100%;
	}

	.category-episodes .vhsl {
		width: 100%;
		height: 0;
		padding-bottom: 17.78%; /* 191/1074, unchanged by box width */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		font-size: 5.59vw; /* 5.77 * 0.96875 */
		word-spacing: -0.090vw; /* -0.093 * 0.96875 */
		line-height: normal;
	}

	.category-episodes .vhsl a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/* ===== /music archive: .musicplayer's own aspect-ratio box (same
	   24.68% ratio as the mobile block above — this is width-relative
	   padding-bottom geometry, not vw-based text, so unlike /blog's
	   0.474609375 and /episodes' 0.96875 corrections just above, it
	   needs no tablet-inset correction factor at all) and the
	   .musicshelf/.rackmountplacer shelf, which keeps its natural 2-up
	   layout here — unlike /vault's 3-down-to-2 or /blog's already-2
	   grid, this was never a grid/column class to begin with, just two
	   537px images floating side by side inside a 1074px container
	   (2 x 537 = 1074 exactly, see the mobile block's own comment
	   above). The fluid tablet equivalent is the same float, at
	   width:50% instead of a fixed 537px — float:left itself is left
	   to the unscoped desktop .rackmountplacer img rule above, not
	   redeclared here, same as every other tablet rule in this file
	   that only needs to override sizing. No font-size/word-spacing
	   anywhere in this branch (.musicplayer is a bare background box,
	   .rackmountplacer has no caption/title, just the image), so this
	   needed none of the vw-based correction-factor math /blog's and
	   /episodes' text-bearing rules above did. ===== */
	.category-music .musicplayer {
		width: 100%;
		height: 0;
		padding-bottom: 24.68%; /* 270/1094, unchanged by box width */
		background-size: 100% 100%;
		margin: 0;
	}

	.category-music .musicshelf,
	.category-music .rackmountplacer {
		width: 100%;
		margin: 0;
	}

	.category-music .rackmountplacer img {
		width: 50%;
	}

	/* ===== /gallery archive (the landing page — see the Mobile Layout
	   section above for the full writeup). Same single-column shape as
	   /episodes' .vhsl, not /music's 2-up .rackmountplacer — these
	   spine images are wide/short (1045x147), not square-ish, so there
	   was never a case for a 2-up tablet layout here the way music's
	   already-square-ish covers got. No vw-based text correction
	   needed for the same reason /music's own tablet block didn't need
	   one: nothing here is text sized in vw, just image width/height
	   and margin/clip-path percentages that resolve against the
	   image's own (fluid, but internally consistent) box either way,
	   same math as the mobile block above, unaffected by the shared
	   12px #content inset since that inset only matters for vw units,
	   which resolve against the viewport rather than the container. */
	.mobile-shell .albumgallery {
		margin: 0;
	}

	/* .albumgallery .albums — same rescope and same reasoning as the
	   Mobile Layout block's own copy of this fix above. */
	.mobile-shell .albumgallery .albums {
		display: block;
		width: 100%;
	}

	.mobile-shell .albumgallery .albums img {
		width: 100%;
		height: auto;
	}

	/* :nth-child(N of .albums), not :nth-of-type(N) — counts position
	   among .albums siblings specifically, same defensive reasoning as
	   /Main Tablet Layout's .thevault rule further down. */
	.mobile-shell .albumgallery .albums:nth-child(2 of .albums) img {
		margin-top: -1.1483%; /* -12/1045 */
	}
	.mobile-shell .albumgallery .albums:nth-child(3 of .albums) img {
		margin-top: -1.6268%; /* -17/1045 */
	}
	.mobile-shell .albumgallery .albums:nth-child(4 of .albums) img {
		margin-top: -0.9569%; /* -10/1045 */
	}
	.mobile-shell .albumgallery .albums:nth-child(1 of .albums) img {
		margin-top: -0.6699%; /* -7/1045 */
		clip-path: inset( 4.7619% 0 0 0 ); /* 7/147 */
	}
	.mobile-shell .albumgallery .albums:nth-child(5 of .albums) img {
		margin-top: -0.8612%; /* -9/1045 */
		margin-bottom: -0.5742%; /* -6/1045 */
		clip-path: inset( 0 0 4.0816% 0 ); /* 6/147 */
	}

	/* ===== /merch archive: same call as /music's own tablet block
	   immediately above, and for the identical reason — .rackmountmerch
	   was never a real grid/column class either, just two 538px images
	   floating side by side inside #content (see "/merch Mobile
	   Layout" above for the full writeup). Keeps the natural 2-up
	   layout, float:left left to the unscoped desktop .rackmountmerch
	   img rule (not redeclared here, same convention as /music's own
	   tablet rule). padding:0 drops the same 12.5px gutter the mobile
	   block already dropped, matching /vault's own .vault3 precedent
	   at both breakpoints, not just one. No font-size/word-spacing
	   anywhere in this branch (.rackmountmerch has no caption/title,
	   just the image) so, like /music, this needed none of the
	   vw-based correction-factor math /blog's and /episodes' own
	   text-bearing tablet rules needed. ===== */
	.category-merch .rackmountmerch {
		padding: 0;
	}

	.category-merch .rackmountmerch img {
		width: 50%;
	}

	/* ===== /photos archive: 3 columns at tablet (down from desktop's
	   4), same shared-class scoping and same proportional-gutter
	   reasoning as the Mobile Layout block above — see that block's
	   own comment for why .mobile-shell .rack-content--gallery (not
	   .category-photos) is correct here, and why the 13/1045 = 1.2440%
	   ratio needs no tablet-specific correction factor the way /blog's
	   and /episodes' own vw-based text rules did.

	   column-count's `3` is now a fallback only, not hardcoded — a
	   real bug (confirmed via DOM measurement, not just visually) on
	   two small [wahnsinn_gallery ids="..."] instances on the RIP Joe
	   Hornacek post: a 2- or 4-item masonry gallery forced into 3
	   columns doesn't have enough items to fill the third column, so
	   the gallery's content only occupies its box's left ~2/3, reading
	   as left-justified even though the box itself is correctly
	   centered. Overridable per call via [wahnsinn_gallery]'s
	   `tablet_cols` attribute (functions.php section 16), which sets
	   --wahnsinn-gallery-cols-tablet inline. The /artwork archive's own
	   hardcoded markup never sets that property, so it (and every
	   [wahnsinn_gallery] call that doesn't set tablet_cols) keeps
	   resolving to this same `3`. ===== */
	.mobile-shell .rack-content--gallery {
		column-count: var(--wahnsinn-gallery-cols-tablet, 3);
		column-gap: 1.2440%; /* 13/1045 */
		padding: 1.2440% 0;
	}

	.mobile-shell .masonry-item {
		margin: 0 0 1.2440% 0;
	}

	/* ===== /gifs archive: 2 columns at tablet (down from desktop's
	   3, via .vault3 — /gifs literally reuses /vault's own outer
	   wrapper class, not a lookalike, see the Mobile Layout block's
	   own comment above), same call and same numbers as /vault's own
	   tablet block above — a new rule, not an edit to that selector.
	   .gifpreview keeps its own real ratio (263.2/350.2 = 75.1571%,
	   not .preview's 75.1%) and the same object-fit:cover fix the
	   mobile block uses — the owner found at least one real GIF here
	   too whose native ratio doesn't fill the box, leaving a visible
	   gap at one edge under the original letterbox technique. ===== */
	.category-gifs .vault3 {
		float: left;
		clear: none;
		padding: 0;
		margin: 0;
		width: 50%;
	}

	.category-gifs .gifpreview {
		width: 100%;
		height: 0;
		padding-bottom: 75.1571%; /* 263.2/350.2 */
		position: relative;
		margin: 0;
	}

	.category-gifs .gifpreview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.category-gifs .gifpreview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		display: block;
	}

	/* ===== /zines archive: 2 columns at tablet (down from desktop's
	   3, via .vault3). .boxpreview keeps its own real content-area
	   ratio (452/350.2 = 129.0691%) and the same object-fit:cover
	   technique as the mobile block. Duplicated here rather than
	   inherited, since padding-bottom resolves against the box's own
	   current width (50% of .vault3 here vs. 100% at mobile).

	   Unlike mobile, tablet gets a real column gutter. Column width is
	   (100% - gutter%) / 2, not a plain 50/50 split, so a single
	   gutter fits between the two columns with both outer edges still
	   landing flush at 0%/100% — applying the gutter as padding-left
	   on every item (desktop's own technique) insets the first column
	   from the edge too, which only reads as intentional at desktop's
	   3-column width, not 2. The gutter itself is margin-left on the
	   second column only (:nth-of-type(2n)).

	   Row gap (margin-bottom) is on THIS rule, not .boxpreview's —
	   percentage margin/padding resolves against each element's OWN
	   containing block, and .boxpreview's (its parent .vault3) is
	   narrower than #content once the gutter math above is in play, so
	   the same percentage number on each would produce two different
	   pixel widths. ===== */
	.category-zines .vault3 {
		float: left;
		clear: none;
		padding: 0;
		margin: 0 0 2.1416% 0; /* row gap — half of the mobile block's 4.2833%, per the owner's 2026-07-31 ask; unaffected by the column-width change above since it's independent of the gutter's own placement */
		width: 48.9292%; /* (100% - 2.1416% gutter) / 2 — NOT a plain 50%, so a real gutter fits between columns with both outer edges still flush */
	}

	/* :nth-child(of S), not :nth-of-type — counts position among .vault3
	   siblings specifically rather than by tag, avoiding the tag-vs-class
	   miscount this project has hit elsewhere (see /Main Tablet Layout's
	   .thevault rule above). */
	.category-zines .vault3:nth-child(2n of .vault3) {
		margin-left: 2.1416%; /* the actual gutter — only before the second/right column, so the first/left column stays genuinely flush against #content's own edge */
	}

	.category-zines .boxpreview {
		width: 100%;
		height: 0;
		padding-bottom: 129.0691%; /* 452/350.2 */
		position: relative;
		margin: 0;
	}

	.category-zines .boxpreview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.category-zines .boxpreview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		display: block;
	}

	/* .wahnsinn-hoofsip-grid at tablet — 3 columns (down from desktop's
	   4), per a 2026-07-31 follow-up revising the original "4 stays fine
	   at tablet" call. .mobile-shell-scoped, not .category-zines-only —
	   same reasoning as the mobile block's own rule above: the shortcode
	   itself isn't category-specific, it just happens that /zines is its
	   only live user today. Unlike the mobile block's own vw derivation
	   (grid width = 100vw, no inset), this single-post rack chrome's
	   "printed area" is a real, non-trivial fraction of the viewport at
	   this breakpoint, not the full width — measured live via
	   getBoundingClientRect(), not assumed: 424.91/768 = 55.33% at the
	   range's own 768px floor, 574.12/1024 = 56.07% at its ceiling — a
	   small (~1.3%) drift across the range, not a perfectly constant
	   percentage, most likely from a mix of percentage- and fixed-px-
	   based measurements upstream in the rack chrome's own tablet
	   conversion. Anchored to the 768px floor for the same reason
	   /blog's 0.474609375 and /episodes' 0.96875 tablet corrections
	   were: text lands very slightly smaller (safer, not tighter) than
	   the ideal ratio at the range's own 1024px ceiling, never larger.

	   Same 0.90 safety factor as the mobile block above, and for the
	   identical reason — see that block's own comment for the full
	   writeup (8 of 36 real HOOFSIP summaries clipped with an exact
	   desktop-ratio match, none clipped with 0.90 applied). Re-verified
	   independently at this breakpoint, not assumed to carry over from
	   the mobile check: zero of 36 real summaries clipped at 768px or
	   1024px. */
	.mobile-shell .wahnsinn-hoofsip-grid {
		grid-template-columns: repeat(3, 1fr);
	}

	.mobile-shell .wahnsinn-hoofsip-grid-title {
		font-size: 1.5595vw; /* 14/149 × 100/3 × 0.553268 × 0.90 */
		line-height: 1.7823vw; /* 16/149 × 100/3 × 0.553268 × 0.90 */
		padding: 0.3342vw 0.6684vw; /* 3/149, 6/149 × 100/3 × 0.553268 × 0.90 */
	}

	.mobile-shell .wahnsinn-hoofsip-grid-summary {
		height: 9.3573vw; /* 84/149 × 100/3 × 0.553268 × 0.90 */
		font-size: 1.3368vw; /* 12/149 × 100/3 × 0.553268 × 0.90 */
		line-height: 1.7823vw; /* 16/149 × 100/3 × 0.553268 × 0.90 */
		padding: 0 0.6684vw 0.4456vw; /* 6/149, 4/149 × 100/3 × 0.553268 × 0.90 */
	}

	/* /404 — same stacking reasoning as the /404 Mobile Layout block's
	   own copy of this rule further up this file: #leftmenu's fixed
	   350.2px plus #container's 725px min-width floor don't fit this
	   range either. #hed itself needs no copy here — it's already
	   fluid at this breakpoint via the unscoped .mobile-shell #hed
	   rule above (never hidden at tablet for anyone), so 404 inherits
	   that for free, same as it inherits #hedmobile's own tablet
	   sizing generically.

	   width:calc(100% - 24px)/margin:0 auto — the same 12px-per-side
	   rack-bar frame inset .single-30mom #content gets at this same
	   breakpoint (see that rule above), applied once here on the
	   shared flex wrapper rather than separately on #leftmenu AND
	   #container, so both stacked images sit inset from the frame
	   instead of running edge to edge — deliberately NOT applied in
	   the mobile block above, which stays flush edge-to-edge (0
	   inset), matching every other join's own mobile/tablet split. */
	.mobile-shell.error404 .main-columns {
		flex-direction: column;
		gap: 0;
		width: calc(100% - 24px);
		margin: 0 auto;
	}

	.mobile-shell.error404 #leftmenu {
		width: 100%;
		margin-left: 0;
	}

	/* #leftmenu li img's display:block fix applies here too via the
	   plain .mobile-shell #leftmenu li img rule under "/Main Tablet
	   Layout" below — see the mobile block's own copy of this note. */

	.mobile-shell.error404 .sidebargif {
		width: 100%;
		margin-left: 0;
	}

	/* order:-1 — same reordering as the mobile block's own copy above:
	   .wrap's 404.gif renders first, sidebar gif last, right above
	   the footer. */
	.mobile-shell.error404 #container.one-column {
		flex: none;
		width: 100%;
		min-width: 0;
		order: -1;
	}

	/* /artifacto — same reasoning as the /Artifacto Mobile Layout
	   block's own copy above, needs its own copy since this is a
	   separate media query. Plain width:100%, NOT another
	   calc(100% - 24px) — #container already carries .single-30mom
	   (confirmed by reading artifacto.php), so #content is already
	   inset 12px-per-side by the existing .single-30mom #content rule
	   above; a second inset here would double it to 24px-per-side,
	   confirmed live as a real bug before landing this fix (measured
	   x:24 instead of the intended x:12). */
	.mobile-shell .artifactowrap {
		width: 100%;
		height: auto;
		margin: 0;
	}

	/* .rack-content--img's own geometry (900/984 fixed-to-fluid) is
	   shared with mobile — see the merged @media(max-width:1024px)
	   rule after "End /404 Mobile Layout". */
	.mobile-shell .artifactowrap .rack-content--img iframe {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
	}
}

/****************************
    End /vault + /blog Tablet Layout
**********************************************/

/****************************
    /Main Tablet Layout — main.php, the site's actual front page.
    Fully responsive with NO content changes — same items/order,
    sidebar stays side-by-side with content (unlike mobile, which
    stacks it). First real side-by-side sidebar+content tablet layout
    in this theme (404.php's own tablet block stacks too), so
    .main-columns' flex split and the vault-tape 2-up pairing below
    are new percentage math, not a reused pattern.

    Scoping follows the Mobile Layout block above: plain .mobile-shell
    selectors throughout, except .thevault/#leftmenu ancestor scopes
    where .preview/.vhssm/.albums need genuinely different numbers.

    The decorative rackbars.png sliver visible through the #leftmenu/
    #container seam at desktop is reproduced here as two
    absolutely-positioned, z-index:-1 pseudo-elements, each an unscaled
    window onto rackbars.png via negative background-position — same
    technique as the shared #wrapper::before/::after edge bars, except
    these sit at a PERCENTAGE left offset (matching #leftmenu's/
    .thevault's own width) so they track the fluid layout instead of a
    fixed position. Trade-off: the window's on-screen size drifts
    slightly from the source art's native pixel width across this
    range, the same small accepted margin this file's vw text
    conversions carry elsewhere.
**********************************************/
@media (min-width: 768px) and (max-width: 1024px) {

	/* .mainpromo — same fix and reasoning as the Mobile Layout block's
	   own copy above (the video's width/height HTML attributes
	   otherwise still govern its rendered size); needs its own copy
	   since this is a separate media query. */
	.mobile-shell .mainpromo {
		width: 100%;
		height: auto;
	}

	/* calc(100% - 24px)/margin:0 auto — the same 12px-per-side
	   rack-bar frame inset every other tablet join uses (see
	   .single-30mom #content above), applied once on the shared flex
	   wrapper rather than separately on #leftmenu AND #container.
	   gap reproduces desktop's own 12.8px seam spacing as a
	   percentage of #wrapper's native 1100px width (12.8/1100) —
	   display:flex/align-items:flex-start are already set by the
	   unscoped desktop .main-columns rule and don't need repeating. */
	.mobile-shell .main-columns {
		position: relative;
		width: calc(100% - 24px);
		margin: 0 auto;
		gap: 1.1636%; /* 12.8/1100 */
	}

	/* The leftmenu/container seam sliver — left matches #leftmenu's
	   own width % below exactly, so this window always starts right at
	   #leftmenu's own right edge; width matches .main-columns' own gap
	   % above, so the window is exactly as wide as the visible gap.
	   -363.2px is the same x=363.2 rackbars.png now shows through this
	   seam at desktop (13px leftmenu margin + 350.2px leftmenu width),
	   unscaled — background-position shifts the image left by that
	   much so the window's own x=0 lands on the image's x=363.2. */
	.mobile-shell .main-columns::before {
		content: '';
		position: absolute;
		top: 0;
		height: 100%;
		left: 31.8364%; /* matches #leftmenu's width below */
		width: 1.1636%; /* matches .main-columns' own gap above */
		background-image: url('/assets/images/structure/rackbars.png');
		background-repeat: repeat-y;
		background-position: -363.2px 0;
		z-index: -1;
		pointer-events: none;
	}

	/* margin-left:0, NOT the desktop ratio (13/1100) — that margin
	   only exists at desktop because #wrapper's own background-image
	   provides the frame border there with nothing else clearing it.
	   At this breakpoint .main-columns' own calc(100% - 24px) above
	   already provides that same 12px-per-side clearance once;
	   keeping #leftmenu's own margin on top of it doubles the inset. */
	.mobile-shell #leftmenu {
		width: 31.8364%; /* 350.2/1100 */
		margin-left: 0;
		flex-shrink: 0;
	}

	/* Same fix and reasoning as the Mobile Layout block's own copy —
	   needs its own copy since this is a separate media query. */
	.mobile-shell #leftmenu li img {
		width: 100%;
		height: auto;
		display: block;
	}

	/* .sidebarmiddle — same fix and reasoning as the Mobile Layout
	   block's own copy above. */
	.mobile-shell .sidebarmiddle {
		background-size: 100% 6px;
	}

	/* .sidebargif/.sidebarflyer — kept VISIBLE and fluid here, unlike
	   the Mobile Layout block (which hides them). Their shared,
	   unscoped rule keeps a fixed width:344px, wider than #leftmenu's
	   own ~274px at this breakpoint, so it needs the same fixed-to-100%
	   conversion as every other sidebar element in this block. */
	.mobile-shell .sidebargif,
	.mobile-shell .sidebarflyer {
		width: 100%;
		margin-left: 0;
	}

	/* Drops the desktop flex:1/min-width:725px floor — the vault-tape
	   pairing below is fluid (percentage-based) now, so it no longer
	   needs a fixed-px floor to keep 2 tapes fitting side by side.
	   position:relative is for the ::before seam-bar window below. */
	.mobile-shell .one-column#container {
		position: relative;
		flex: 1;
		min-width: 0;
	}

	/* The between-paired-tapes seam sliver, same technique and
	   reasoning as .main-columns' own copy above — left matches
	   .thevault's own width % further below, so this window starts
	   right at the first tape of each pair's own right edge; width
	   matches .thevault:nth-child(2n of .thevault)'s own margin-left %
	   (the real gutter), so the window is exactly as wide as that gutter.
	   -726.2px is the same x=726.2 rackbars.png shows through this gap
	   at desktop (#container's own 376px offset + the first tape's
	   350.2px width), unscaled. Sits behind #container's ENTIRE
	   height (position:relative + z-index:-1 on the parent above), the
	   same way desktop's single #wrapper background shows through
	   every row's gap at once without repeating the rule per row —
	   it only becomes visible where there's no opaque tape content
	   over it, i.e. every row's own gutter. */
	.mobile-shell .one-column#container::before {
		content: '';
		position: absolute;
		top: 0;
		height: 100%;
		left: 49.1718%; /* matches .thevault's width further below */
		width: 1.6565%; /* matches .thevault:nth-child(2n of .thevault)'s margin-left further below */
		background-image: url('/assets/images/structure/rackbars.png');
		background-repeat: repeat-y;
		background-position: -726.2px 0;
		z-index: -1;
		pointer-events: none;
	}

	/* .sidebarbottom stays VISIBLE and fluid here, unlike the Mobile
	   Layout block above — tablet keeps every piece of content per the
	   owner's spec. 11.1359% = 39/350.2, .sidebarbottom's own
	   containing block (always #leftmenu's own width, whatever that
	   resolves to). */
	.mobile-shell .sidebarbottom {
		height: 0;
		padding-bottom: 11.1359%; /* 39/350.2 */
		background-size: 100% 100%;
	}

	/* ===== Vault-tape grid: still 2-up, same pairing shape as
	   desktop, just fluid — NOT /vault's own tablet grid's zero-gutter
	   shortcut, since main.php's desktop pairing has a real, non-zero
	   12px gutter between the two tapes in a row (.thevault's own
	   padding-right). Re-derived as "(100% - gutter%) / 2" per the
	   /zines archive's own "a real gutter needs its own math" lesson,
	   not copied from a zero-gutter precedent: gutter = 12/724.4 =
	   1.6565% (724.4 = the desktop pair's own total width, .preview's
	   350.2 + the 12px gutter, ×2 — the containing-block reference
	   this percentage resolves against). clear:none (not desktop's
	   alternating clear:right) since the widths themselves now do the
	   2-per-row wrapping, matching /vault's own tablet grid's choice
	   of the same mechanism. ===== */
	.mobile-shell .thevault {
		float: left;
		clear: none;
		padding: 0;
		margin: 0;
		width: 49.1718%; /* (100% - 1.6565%) / 2 */
	}

	/* :nth-child(2n of .thevault), not :nth-of-type(2n) — nth-of-type
	   counts by tag, and .thevault shares its <figure> tag with the 3
	   preceding .vhs episode spines, so a plain nth-of-type miscounts
	   (same bug already hit on the mobile hide-rule above). The
	   "of S" selector-list form counts position only among siblings
	   matching .thevault itself, ignoring the .vhs figures entirely —
	   correct regardless of how many spines precede it. Supported in
	   every browser this project targets (Safari 9+, Chrome/Edge 111+,
	   Firefox 113+). */
	.mobile-shell .thevault:nth-child(2n of .thevault) {
		margin-left: 1.6565%; /* 12/724.4 */
	}

	/* Same padding-bottom aspect-ratio technique as the mobile block's
	   own copy — 75.1% (263/350.2) doesn't change with box width, and
	   .preview's own containing block is always .thevault (100% of
	   it), so this is correct at any width regardless of #container's
	   own fluid size. */
	.mobile-shell .thevault .preview {
		width: 100%;
		height: 0;
		padding-bottom: 75.1%; /* 263/350.2 */
		position: relative;
		margin: 0;
	}

	.mobile-shell .thevault .preview a {
		position: absolute;
		inset: 0;
		display: block;
	}

	.mobile-shell .thevault .preview img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
	}

	/* font-size/word-spacing: derived, not measured — 21/350.2=5.997%
	   of .vhssm's own box width is the desktop ratio (confirmed
	   against the mobile block's own 6vw, where the box is ~100vw);
	   at this breakpoint .thevault's own column is roughly 31.35% of
	   the viewport (#main-columns' 24px inset × #leftmenu's ~31.84%
	   share × this column's 49.17% share of #container, evaluated at
	   this range's own 768px floor per this file's usual
	   anchor-to-floor convention), so 5.997% x 31.35vw = 1.88vw, then
	   the same 0.92 safety factor /blog's own tablet text uses for a
	   derived-not-measured vw fit — 1.88 x 0.92 = 1.73vw. Verify live
	   and adjust if the caption ever looks cramped or oversized. */
	.mobile-shell .thevault .vhssm {
		width: 100%;
		height: 0;
		padding-bottom: 19.13%; /* 67/350.2 */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		padding-left: 0;
		font-size: 1.73vw;
		word-spacing: -0.0823vw;
	}

	.mobile-shell .thevault .vhssm a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
		line-height: normal;
	}

	/* .vhs — single full-width-of-#container column (never paired,
	   even at desktop), so unlike .vhssm above there's no further
	   50%-of-container halving: its own viewport-relative fraction is
	   just #container's own (~63.76vw at this range's 768px floor).
	   5.9072% (42/711, the mobile block's own ratio) x 63.76vw =
	   3.766vw, x the same 0.92 safety factor = 3.465vw. Word-spacing
	   the same way: 0.1406% x 63.76 x 0.92 = 0.0824vw. */
	.mobile-shell .vhs {
		width: 100%;
		height: 0;
		padding-bottom: 19.128%; /* 136/711, unchanged by box width */
		position: relative;
		background-size: 100% 100%;
		margin: 0;
		font-size: 3.465vw;
		word-spacing: -0.0824vw;
		line-height: normal;
	}

	.mobile-shell .vhs a {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/* .tray/.creditsbutton — the >>VAULT<< button, fluid here (NOT
	   dropped, unlike the Mobile Layout block above — tablet keeps
	   every piece of content). Same shape as .vhs above: single
	   full-width-of-#container box. */
	.mobile-shell .tray {
		position: relative;
		width: 100%;
		height: 0;
		padding-bottom: 5.9072%; /* 42/711 */
		background-size: 100% 100%;
	}

	/* .creditsbutton was a normal-flow child offset via padding at
	   desktop (top:1px, left:294px within .tray's 711x42 box) — same
	   "padding-percentages resolve against width even for top/bottom,
	   which breaks once the parent goes to height:0" issue the
	   .vaultbutton/.artibtn rules below solve the same way: absolute
	   positioning instead, with top/height resolving against .tray's
	   real (padding-derived) height and left/width against its real
	   width. */
	.mobile-shell .creditsbutton {
		position: absolute;
		left: 41.3502%; /* 294/711 */
		top: 2.381%; /* 1/42 */
		width: 16.737%; /* 119/711 */
		height: 97.619%; /* 41/42 */
		padding: 0;
	}

	/* creditsbutton.png is a real 351x39 3-frame sprite (confirmed via
	   sips, 117px/frame) — desktop's own 0/-117px/-234px offsets map
	   directly to frames 0/1/2 with no tiling-wraparound trick (unlike
	   .vaultbutton/.artibtn below), so background-position is just
	   0%/50%/100% in the same link/hover/active order. flex centering
	   replaces the desktop line-height:39px vertical-centering trick,
	   which can't survive a variable box height. font-size/
	   letter-spacing derived the same way as .vhs above: 13/711 and
	   1/711 as a fraction of the box's own width, x 63.76vw (this
	   box's own viewport-relative fraction, same as .vhs since neither
	   is split into columns), x the same 0.92 safety factor. */
	.mobile-shell .creditsbutton a:link,
	.mobile-shell .creditsbutton a:visited,
	.mobile-shell .creditsbutton a:hover,
	.mobile-shell .creditsbutton a:active {
		width: 100%;
		height: 100%;
		background-repeat: no-repeat;
		background-size: 300% 100%;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 1.0725vw;
		letter-spacing: 0.0825vw;
	}
	.mobile-shell .creditsbutton a:link,
	.mobile-shell .creditsbutton a:visited {
		background-position: 0% 0;
	}
	.mobile-shell .creditsbutton a:hover {
		background-position: 50% 0;
	}
	.mobile-shell .creditsbutton a:active {
		background-position: 100% 0;
	}

	/* .vaultcounter/.vaultbutton, .sidetray/.artibtn — same shape and
	   same fix as the Mobile Layout block's own copies above (a real
	   background-image tray plus an absolutely-positioned sprite
	   button on top); needs its own copy since this is a separate
	   media query. */
	.mobile-shell .vaultcounter {
		position: relative;
		width: 100%;
		height: 0;
		padding-bottom: 24.5714%; /* 86/350 */
		background-size: 100% 100%;
		margin-bottom: 2.8571%; /* 10/350 */
	}

	.mobile-shell .vaultbutton {
		position: absolute;
		left: 69.4286%; /* 243/350 */
		top: 50%; /* 43/86 */
		width: 18%; /* 63/350 */
		height: 33.7209%; /* 29/86 */
		padding: 0;
	}

	.mobile-shell .vaultbutton a:link,
	.mobile-shell .vaultbutton a:visited,
	.mobile-shell .vaultbutton a:hover,
	.mobile-shell .vaultbutton a:active {
		width: 100%;
		height: 100%;
		background-repeat: no-repeat;
		background-size: 300% 100%;
	}
	.mobile-shell .vaultbutton a:link,
	.mobile-shell .vaultbutton a:visited {
		background-position: 50% 0;
	}
	.mobile-shell .vaultbutton a:hover {
		background-position: 0 0;
	}
	.mobile-shell .vaultbutton a:active {
		background-position: 100% 0;
	}

	.mobile-shell .streamingbuttons {
		width: 100%;
		margin-left: 0;
	}

	.mobile-shell .streamingbuttons img {
		width: 33.314%; /* 114.6/344 */
		height: auto;
	}

	.mobile-shell #leftmenu .albums {
		display: block;
		width: 100%;
	}

	.mobile-shell #leftmenu .albums img {
		width: 100%;
		height: auto;
	}

	.mobile-shell .sidetray {
		position: relative;
		width: 100%;
		height: 0;
		padding-bottom: 22.2857%; /* 78/350 */
		background-size: 100% 100%;
	}

	.mobile-shell .artibtn {
		position: absolute;
		left: 40%; /* 140/350 */
		top: 2.5641%; /* 2/78 */
		width: 20%; /* 70/350 */
		height: 94.8718%; /* 74/78 */
		padding: 0;
	}

	.mobile-shell .artibtn a:link,
	.mobile-shell .artibtn a:visited,
	.mobile-shell .artibtn a:hover,
	.mobile-shell .artibtn a:active {
		width: 100%;
		height: 100%;
		background-repeat: no-repeat;
		background-size: 300% 100%;
	}
	.mobile-shell .artibtn a:link,
	.mobile-shell .artibtn a:visited {
		background-position: 50% 0;
	}
	.mobile-shell .artibtn a:hover {
		background-position: 100% 0;
	}
	.mobile-shell .artibtn a:active {
		background-position: 0 0;
	}
}
/****************************
    End /Main Tablet Layout
**********************************************/

/****************************
    /vault + /blog Load More (all widths — NOT inside the 767px block
    above)

    The archive query is capped to 24 posts/page in functions.php
    (wahnsinn_vault_archive_posts_per_page, now shared by /vault and
    /blog); this button/link is what lets a visitor reach the rest
    without a hard page reload, on desktop and mobile alike. The base
    rule and its 767px override are .mobile-shell-prefixed (same
    mechanism as the /vault Mobile Layout section above — see
    functions.php section 26) so /blog gets them too; the 768-1024px
    tablet override below is .mobile-shell-prefixed too, now that
    /blog has its own Phase 2 fluid tablet layout and the same
    #content inset that override assumes (see "/vault + /blog Tablet
    Layout" above). The ids/classes below were also renamed from
    #vault-archive-posts/.vault-load-more-wrap/#vault-load-more to
    generic #archive-posts/.archive-load-more-wrap/#archive-load-more,
    since category.php now renders them on both archives. See
    Vault Work/HANDOVER.md, "Endless/long page length".

    Same sprite-sheet button technique as .creditsbutton above (the
    homepage's own ">>VAULT<<" link) — load-more-btn.png is a 3-frame
    351x39 sprite (normal/hover/active side by side, same convention
    as creditsbutton.png), scaled up to 51px tall (this button's own
    original padded height) via background-size, keeping every frame
    boundary an exact pixel value: 39px -> 51px is a 51/39 (=17/13)
    scale, and 117px-per-frame native width happens to land on a
    whole pixel at that scale (117 * 51/39 = 153 exactly), so
    background-size/position below use round numbers, not fractional
    ones. If load-more-btn.png is ever re-exported at a different
    native size, re-derive these rather than reusing them as-is.

    The tray band (sidetray.png, tiled) is capped to the same 51px
    height as the button via background-size — a repeating tile
    taller than the button would read as a box around it instead of a
    flush strip level with it. Width is intentionally NOT capped: the
    tray spans the full row and tiles horizontally as many times as
    needed, with the button centered on top of it via flexbox.

    #archive-posts gets `display: flow-root` here rather than leaving
    .archive-load-more-wrap's own `clear` to do double duty as a
    clearfix — without it, #archive-posts collapses around its floated
    .vault3 children on desktop, and clearance from the wrap's own
    `clear:both` suppresses its top margin via margin-collapsing
    (positive clearance from clearing a float overrides a would-be top
    margin) while the bottom margin renders normally — so the same CSS
    produced an asymmetric gap only where .vault3 is actually floated
    (desktop, not mobile). flow-root removes the need for `clear` to
    do that job at all, so margin behaves symmetrically everywhere.
****************************/

.mobile-shell #archive-posts {
	display: flow-root;
}

/* Fixed 1076px on desktop (#wrapper is a fixed 1100px there), not
   100%: #wrapper's own background, rackbars.png, is a 1100px-wide
   image, and each edge is actually TWO separate visual pieces:
     x=0-11    (12px) light silver strip  — the page's own frame
                                              border, must stay visible
     x=12      (1px)  dark bevel line     — the seam between them
     x=13-43   (31px) tan rack-mount bar,
                       bolt hole included  — this is the "hole" that
                                              needs covering
   (mirrored on the right: bar at 1056-1086, bevel at 1087, frame at
   1088-1099.) The tray needs to cover the bar+hole without touching
   the frame strip — 12px is the right inset to clear just the frame
   strip (x=0-11) while the tray's own edge covers the bevel line and
   bar+hole from x=12 inward. 1100 - 12*2 = 1076, centered with auto
   margins. Reset to 100% (edge-to-edge) in the 767px mobile block,
   where #wrapper itself goes fluid and rackbars.png isn't in play the
   same way. */
.mobile-shell .archive-load-more-wrap {
	width: 1076px;
	height: 51px;
	margin: 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	background: url('/assets/images/structure/sidetray.png') repeat;
	background-size: auto 51px;
}

.mobile-shell #archive-load-more {
	display: block;
	width: 153px;
	height: 51px;
	line-height: 51px;
	font-family: 'MOM', monospace;
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: 1px;
	text-align: center;
	text-decoration: none;
	color: #282828;
	background: url('/assets/images/structure/load-more-btn.png') 0 0;
	background-size: 459px 51px;
	animation: facebreathe 3.15s ease-in-out infinite;
}

.mobile-shell #archive-load-more:hover {
	background-position: -153px 0;
	color: #383838;
}

.mobile-shell #archive-load-more:active {
	background-position: -306px 0;
	color: #383838;
}

.mobile-shell #archive-load-more[aria-disabled="true"] {
	opacity: 0.6;
	pointer-events: none;
}

/* Fluid below 1024px, covering both the mobile and tablet ranges in
   one rule — #wrapper/#content are no longer the fixed 1100px the
   1076px rule above assumes at either range (see "/vault + /blog
   Tablet Layout" above and the mobile block's own #wrapper rule), so
   a fixed-width tray would overflow and drift off-center as the
   viewport narrows. */
@media (max-width: 1024px) {
	.mobile-shell .archive-load-more-wrap {
		width: 100%;
		margin: 0;
	}
}

/****************************
    End /vault + /blog Load More
**********************************************/

 /*
  Quanta Microgen 100 Character Generator. Single-element usage:

<div class="cg">...</div> or restyle h1 for <h1 class="cg>"

*/

/* =========================================
   Alignment
========================================= */

.cg-align-left {
  text-align: left;
  justify-content: flex-start;
}

.cg-align-center {
  text-align: center;
  justify-content: center;
}

.cg-align-right {
  text-align: right;
  justify-content: flex-end;
}


/* =========================================
   Base CG Effect
========================================= */

.cg {
  -webkit-text-size-adjust: 100%;
  position: relative;
  flex-shrink: 0;
  overflow: visible;
  isolation: isolate;
  box-sizing: border-box;
  background: transparent;
  white-space: pre-wrap;
  overflow-wrap: break-word;

  text-shadow:
    0 0 0.25px rgba(255, 255, 255, 0.35),
    0 0 0.5px rgba(255, 255, 255, 0.21),
    0 0 1.1px rgba(255, 255, 255, 0.105),
    0 1.5px 0 #000,
    0 -1.5px 0 #000,
    1.5px 0 0 #000,
    -1.5px 0 0 #000,
    -1.25px 0 0 rgba(255, 42, 42, 0.05),
    1.25px 0 0 rgba(42, 212, 255, 0.05),
    3.6px 0 2.7px rgba(255, 0, 60, 0.27),
    -3.6px 0 2.7px rgba(0, 200, 255, 0.27),
    -5.6px 0.8px 1.2px rgba(255, 255, 255, 0.14);

  animation:
    cg-jitter 0.15s steps(2, jump-none) infinite,
    cg-flicker 4s linear infinite,
    cg-tracking-clip 2.5s steps(1) infinite,
    cg-colordrift 6s ease-in-out infinite;
}

.cg::before {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  padding: inherit;
  box-sizing: border-box;
  color: transparent;
  -webkit-background-clip: text;
  background-clip: text;
  pointer-events: none;

  --d1: 0;
  --d2: 0;

  background-image:
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, var(--d1)) 0px,
      rgba(255, 255, 255, var(--d1)) 1px,
      transparent 1px,
      transparent 40px
    ),
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, var(--d2)) 0px,
      rgba(255, 255, 255, var(--d2)) 1px,
      transparent 1px,
      transparent 77px
    ),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.35'/></svg>"),
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.05) 0px,
      rgba(0, 0, 0, 0.05) 1px,
      transparent 1px,
      transparent 5px
    );

  background-blend-mode: screen, screen, overlay, multiply;

  animation:
    cg-noise-shift 0.4s steps(4) infinite,
    cg-dropout-flicker 2s steps(1) infinite;
}


/* =========================================
   Typography Presets
========================================= */

.cg-sidebar {
  font-family: 'quanta', monospace;
  font-weight: 700;
  font-size: 24px;
  line-height: 1.4;
  padding: 24px 0 24px 0;
  color: #fe3527;
}

.cg-footer {
  font-family: 'quanta', monospace;
  font-weight: 400;
  font-size: 16px;
  color: #fe3527;
}


/* =========================================
   Animations
========================================= */

@keyframes cg-jitter {
  0%, 100% { transform: translate(0, 0); }
  8%  { transform: translate(0, 1.8px); }
  50% { transform: translate(0, 1.8px); }
  95% { transform: translate(0, 1.8px); }
  96% { transform: translate(0, 0); }
  97% { transform: translate(0, 1.8px); }
  98% { transform: translate(0, 0); }
}

@keyframes cg-tracking-clip {
  0%, 94%, 98%, 100% { clip-path: none; }
  95% { clip-path: inset(0 0 0 0); }
  96% { clip-path: inset(0 0 0 0); }
  97% { clip-path: inset(0 0 0 0); }
}

@keyframes cg-flicker {
  0%, 100% { opacity: 1; }
  55% { opacity: 0.99; }
  92% { opacity: 1; }
  93% { opacity: 0.98; }
  94% { opacity: 1; }
}

@keyframes cg-colordrift {
  0%, 100% {
    filter:
      contrast(0.963)
      saturate(0.933)
      blur(0.075px)
      blur(var(--cg-blur, 1.4px))
      hue-rotate(0deg);
  }

  50% {
    filter:
      contrast(0.963)
      saturate(1.296)
      blur(0.075px)
      blur(var(--cg-blur, 1.4px))
      hue-rotate(13deg);
  }
}

@keyframes cg-noise-shift {
  0% {
    background-position: 0 0, 0 0, 0 0, 0 0;
  }

  25% {
    background-position: 0 0, 0 0, -20px 10px, 0 0;
  }

  50% {
    background-position: 0 0, 0 0, 15px -15px, 0 0;
  }

  75% {
    background-position: 0 0, 0 0, -10px -10px, 0 0;
  }

  100% {
    background-position: 0 0, 0 0, 0 0, 0 0;
  }
}

@keyframes cg-dropout-flicker {
  0%, 80% {
    --d1: 0;
    --d2: 0;
  }

  81% {
    --d1: 0.5;
    --d2: 0;
  }

  83% {
    --d1: 0;
    --d2: 0;
  }

  84% {
    --d1: 0;
    --d2: 0.35;
  }

  86%, 100% {
    --d1: 0;
    --d2: 0;
  }
}


/* =========================================
   Accessibility
========================================= */


@media (prefers-reduced-motion: reduce) {
  .cg {
    animation: none;
    filter:
      contrast(0.963)
      saturate(1.0)
      blur(var(--cg-blur, 1.4px));
  }

  .cg::before {
    animation: none;

    /* Keep a subtle static texture */
    --d1: 0.12;
    --d2: 0.08;
  }
}
