/* Site-wide utility classes and fluid type scale, carried over verbatim from
   the "Global Styles" embed Webflow injected into every page's <head>. The
   compiled webflow.css / genuine-article-magazine.webflow.css files (linked
   in layout.js) don't include this — it lived in the page HTML itself.

   The original port had this as five separate max-width media queries,
   each with its own independent calc() formula (one per Webflow responsive
   breakpoint). They didn't agree with each other at the breakpoints where
   control passes from one to the next, so the root font-size (and every
   rem-based size sitewide — headings, spacing, the navbar's logo/button)
   jumped abruptly at exactly 1440/1441px, 991/992px, 767/768px, and
   478/479px — as much as +96% for a single pixel of viewport width at the
   478/479 seam. That produced real, visible bugs: a mobile menu-button
   navbar-height dip around 480-580px (worked around separately below) and
   a "too small, especially at iPad" look across 768-991px, where the root
   size troughed at little over half its neighboring values (~7.4-12.4px
   vs ~16px on either side).

   Replaced with a single clamp(), continuous by construction — there's no
   seam left to jump at. Anchored at (375px, 15.383px) and (1440px, 16px):
   both are widths whose current rendering was already implicitly tested
   and never flagged as wrong throughout this project (375px is squarely
   inside the old scale's least-broken tier; 1440px+ was already a flat
   16px). Interpolating between only those two trusted points means common
   phone widths and desktop are close to unchanged, while the previously
   undersized iPad range now lands smoothly between them (768px: 12.4px ->
   15.6px) instead of in a trough. */
html {
  font-size: clamp(15px, calc(15.165746px + 0.057934vw), 16px);
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}
img,
svg {
  display: block;
}
/* Ensure all elements inherit the color from its parent */
a,
.w-input,
.w-select,
.w-tab-link,
.w-nav-link,
.w-nav-brand,
.w-dropdown-btn,
.w-dropdown-toggle,
.w-slider-arrow-left,
.w-slider-arrow-right,
.w-dropdown-link {
  color: inherit;
  text-decoration: inherit;
  font-size: inherit;
}
/* Focus state style for keyboard navigation for the focusable elements */
*[tabindex]:focus-visible,
input[type='file']:focus-visible {
  outline: 0.125rem solid #4d65ff;
  outline-offset: 0.125rem;
}
/* Get rid of top margin on first element in any rich text element */
.w-richtext > :not(div):first-child,
.w-richtext > div:first-child > :first-child {
  margin-top: 0 !important;
}
/* Get rid of bottom margin on last element in any rich text element */
.w-richtext > :last-child,
.w-richtext ol li:last-child,
.w-richtext ul li:last-child {
  margin-bottom: 0 !important;
}
/* Prevent all click and hover interaction with an element */
.pointer-events-off {
  pointer-events: none;
}
/* Enables all click and hover interaction with an element */
.pointer-events-on {
  pointer-events: auto;
}
/* Create a class of .div-square which maintains a 1:1 dimension of a div */
.div-square::after {
  content: '';
  display: block;
  padding-bottom: 100%;
}
/* Make sure containers never lose their center alignment */
.container-medium,
.container-small,
.container-large {
  margin-right: auto !important;
  margin-left: auto !important;
}
/* Apply "..." after 3 lines of text */
.text-style-3lines {
  display: -webkit-box;
  overflow: hidden;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
/* Apply "..." after 2 lines of text */
.text-style-2lines {
  display: -webkit-box;
  overflow: hidden;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* Adds inline flex display */
.display-inlineflex {
  display: inline-flex;
}
/* These classes are never overwritten */
.hide {
  display: none !important;
}
/* Remove default Webflow chevron from form select */
select {
  -webkit-appearance: none;
}
@media screen and (max-width: 991px) {
  .hide,
  .hide-tablet {
    display: none !important;
  }
}
@media screen and (max-width: 767px) {
  .hide-mobile-landscape {
    display: none !important;
  }
}
@media screen and (max-width: 479px) {
  .hide-mobile {
    display: none !important;
  }
}
.margin-0 {
  margin: 0rem !important;
}
.padding-0 {
  padding: 0rem !important;
}
.spacing-clean {
  padding: 0rem !important;
  margin: 0rem !important;
}
.margin-top {
  margin-right: 0rem !important;
  margin-bottom: 0rem !important;
  margin-left: 0rem !important;
}
.padding-top {
  padding-right: 0rem !important;
  padding-bottom: 0rem !important;
  padding-left: 0rem !important;
}
.margin-right {
  margin-top: 0rem !important;
  margin-bottom: 0rem !important;
  margin-left: 0rem !important;
}
.padding-right {
  padding-top: 0rem !important;
  padding-bottom: 0rem !important;
  padding-left: 0rem !important;
}
.margin-bottom {
  margin-top: 0rem !important;
  margin-right: 0rem !important;
  margin-left: 0rem !important;
}
.padding-bottom {
  padding-top: 0rem !important;
  padding-right: 0rem !important;
  padding-left: 0rem !important;
}
.margin-left {
  margin-top: 0rem !important;
  margin-right: 0rem !important;
  margin-bottom: 0rem !important;
}
.padding-left {
  padding-top: 0rem !important;
  padding-right: 0rem !important;
  padding-bottom: 0rem !important;
}
.margin-horizontal {
  margin-top: 0rem !important;
  margin-bottom: 0rem !important;
}
.padding-horizontal {
  padding-top: 0rem !important;
  padding-bottom: 0rem !important;
}
.margin-vertical {
  margin-right: 0rem !important;
  margin-left: 0rem !important;
}
.padding-vertical {
  padding-right: 0rem !important;
  padding-left: 0rem !important;
}
/* Apply "..." at 100% width */
.truncate-width {
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Removes native scrollbar */
.no-scrollbar {
  -ms-overflow-style: none;
  overflow: -moz-scrollbars-none;
}
.no-scrollbar::-webkit-scrollbar {
  display: none;
}
.is-list-loading {
  opacity: 0;
  transition: all 0.3s ease;
}

/* The mobile menu toggle was a <div> in the original Webflow markup, ported
   to a real <button> here for accessibility (keyboard focus, semantics).
   Real buttons carry browser default chrome (background, border) that a
   <div> never had, and nothing in the compiled CSS resets it since it never
   needed to — shows up as a visible gray box over the hero image. */
.navbar2_menu-button {
  background-color: transparent;
  border: none;
}

/* Mobile menu open state: the site CSS makes this panel a full 100dvh
   (entire screen height) with huge 6-6.5rem top/bottom padding — meant to
   vertically center content in a full-screen takeover. With only two links
   in it, that reads as heavy-handed. Sized to wrap its content instead, as
   a compact dropdown right under the nav bar.

   Animation: Webflow's own mechanism shows/hides this panel via a hard
   display:none <-> display:block swap ([data-nav-menu-open] in webflow.css),
   which can't be transitioned — a display change is instant, not animatable.
   Keeping it always rendered (display:block, forced past the generic
   display:block!important toggle via higher specificity) and driving
   visibility through opacity/transform instead lets it slide down and fade
   in smoothly. pointer-events:none while closed keeps its invisible footprint
   from intercepting clicks meant for whatever's behind it.

   Positioning (top:100%) and the stacked/centered link layout used to come
   from [data-nav-menu-open] and each link's .w--nav-link-open class — both
   toggle instantly (no transition) alongside the animated opacity/transform,
   so closing looked like a flash-to-top-of-screen before the fade finished.
   Made both permanent here instead of conditional on the toggle, so opacity
   and transform are the *only* things that ever animate — symmetric open
   and close. Visually harmless while closed since opacity:0 hides it anyway. */
@media screen and (max-width: 991px) {
  .navbar2_menu.is-page-height-tablet {
    display: block !important;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: auto;
    max-height: 70vh;
    padding-top: 2rem;
    padding-bottom: 2rem;
    opacity: 0;
    transform: translateY(-12px);
    pointer-events: none;
    transition: opacity 0.22s ease, transform 0.22s ease;
  }
  .navbar2_menu.is-page-height-tablet[data-nav-menu-open] {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  .navbar2_menu.is-page-height-tablet .navbar2_link {
    display: block;
    text-align: center;
  }
}

/* Hamburger-to-X morph on the mobile nav toggle. Webflow's own runtime does
   this by setting inline transforms via JS on open/close; the compiled CSS
   export doesn't include it, so it's reimplemented here keyed off the
   .w--open class the button already gets. */
.menu-icon2_line-top,
.menu-icon2_line-bottom {
  transition: transform 0.2s ease;
}
.menu-icon2_line-middle {
  transition: opacity 0.2s ease;
}
.navbar2_menu-button.w--open .menu-icon2_line-top {
  transform: translate3d(0, 8px, 0) rotate(45deg);
}
.navbar2_menu-button.w--open .menu-icon2_line-bottom {
  transform: translate3d(0, -8px, 0) rotate(-45deg);
}

.navbar2_menu-button.w--open .menu-icon2_line-middle {
  opacity: 0;
}

/* The hamburger's three lines are plain background-color divs, always the
   site's default dark text color regardless of navbar variant — invisible
   against the homepage's dark hero image. Same fix as the logo swap
   (.is-white), applied here since nothing already covers it. */
.menu-icon2.is-white .menu-icon2_line-top,
.menu-icon2.is-white .menu-icon2_line-middle,
.menu-icon2.is-white .menu-icon2_line-bottom {
  background-color: var(--_primitives---colors--white);
}

/* .text-color-white/.text-color-black are same-specificity (0,1,0) as the
   "ensure inherit" reset above (`.w-nav-link { color: inherit }`), and that
   reset is declared later in this same file, so on nav links it silently
   wins and the utility class never actually applies — the Cart link was
   inheriting the page's default dark text on the homepage's dark hero
   instead of turning white. Never noticed for the black variant because
   the inherited fallback already happens to be black. A compound selector
   here outranks the reset regardless of source order. */
.navbar2_link.text-color-white {
  color: var(--_primitives---colors--white);
}

/* On hover, the generic `.navbar2_link:hover { color: inherit }` rule
   (same specificity, declared later) resets color to whatever this link's
   actual parent computes to. For "Our Story"/"Shop"/"Contact", that's
   still white because their base color comes from an ancestor
   (.navbar2_menu) that inheritance sees fine. Cart's base white comes
   from the rule directly above instead — a direct match on the element
   itself, not inherited — so on hover it fell back past that straight to
   the page's default dark text (black), a jarring flash instead of the
   same fade-to-70%-opacity everything else gets. */
.navbar2_link.text-color-white:hover {
  color: var(--_primitives---colors--white);
}

/* Terms and Conditions link in the newsletter CTA: the site CSS only
   underlines .text-link on hover, and the same "a { color }" specificity
   issue fixed for the footer above applies here too (.section_cta2 already
   sets color:white on the section, but the direct rule on <a> wins over
   inheritance regardless). */
.text-link {
  text-decoration: underline;
}
.section_cta2 a {
  color: var(--_primitives---colors--white);
}

/* Nav "Get the Mag" button wasn't actually anchored to the right edge — a
   real bug, not just a sizing tweak. The site CSS defines justify-self:end
   for its grid cell (#w-node-...746a), but the export only captured that
   declaration inside the <=479px media query, not at the base/desktop
   level, so the button-wrapper defaulted to sitting at the start of its
   grid column instead of flush against the padding-right edge — the actual
   cause of the left/right asymmetry. Applied unconditionally since it's
   correct at every breakpoint, not just desktop. */
.navbar2_button-wrapper {
  justify-self: end;
}

/* "Our Story" and "Contact" were centered as a pair but sitting far apart
   from each other (~250px gap): .w-nav-link, a base framework class both
   links carry, sets margin-left/right:auto, which on flex children (the
   .navbar2_menu row) consumes all free space rather than sitting close
   together. .navbar2_link never overrides it. Resetting to 0 so the two
   links group tightly, centered as a unit, with spacing coming from their
   own padding (.5rem 1rem each) instead. */
.navbar2_link {
  margin-left: 0;
  margin-right: 0;
}

/* Desktop/laptop-only navbar sizing per feedback: bigger logo, more inset
   from the left/top so it doesn't sit flush in the corner. Scoped to
   Webflow's "Desktop" tier (>991px) so tablet/mobile are untouched. */
@media screen and (min-width: 992px) {
  .navbar2_component {
    padding-top: 1rem;
    padding-left: 7%;
    padding-right: 7%;
  }
  .navbar2_logo-link {
    height: 3.25rem;
  }
}

/* Replacing the template's leftover orange accent color (--color-scheme-1--accent,
   an artifact of the site this design was originally built from) per feedback.
   Split into two treatments depending on background:
   - Light backgrounds (plain links like the mailto on the contact page; button
     hover once it's turned white) can safely use the brand burgundy (--red-900,
     same as the button/footer background color) — good contrast either way.
   - Dark/colored backgrounds (nav links over the hero image, footer links on the
     burgundy footer) can't use burgundy for hover text without risking it
     disappearing into the background behind it — an opacity fade instead reads
     as an intentional hover state regardless of what's behind it. */
a:hover,
.button:hover {
  color: var(--red-900);
}
.navbar2_link:hover,
.footer7_link:hover,
.footer7_legal-link:hover {
  color: inherit;
  opacity: 0.7;
  transition: opacity 0.2s ease;
}

/* Contact form submit button: .contact9_form is a single-column CSS grid, so
   its children (including the submit input) stretch to fill the full width by
   default. Sized/aligned to match the other buttons on the site instead. */
.contact9_form input[type='submit'] {
  justify-self: start;
  width: auto;
}

/* The compiled site CSS has a broken interaction at <=479px: it pushes
   .new-ga-about_about_component down 5rem (too much space above the founder
   photo) while separately pulling .margin-top.margin-xxlarge up 5rem (used
   on the "A word from the founder" heading, causing it to overlap the photo
   above it). Neutralizing the component push here; the heading itself uses
   margin-large instead of margin-xxlarge in page.js to sidestep the second
   rule rather than touching that shared utility class globally. */
@media screen and (max-width: 479px) {
  .new-ga-about_about_component {
    margin-top: 0;
  }
}

/* The site CSS has a blanket "a { color: var(--color-scheme-1--text) }" rule
   (black) that directly targets every link. A direct rule on an element
   always wins over an inherited value, so the footer's .text-color-white
   class alone doesn't reach its links even though the dark maroon
   background needs white text for contrast — this overrides it specifically
   for footer links rather than loosening the site-wide default. */
.footer7_component a {
  color: var(--_primitives---colors--white);
}

/* Navbar is position:absolute site-wide, intentional for the homepage so it
   overlays the full-bleed hero image. Pages with no hero before <main>
   (marked .no-hero) have nothing reserving space for it, so their first
   content sits right at the top of the page and the navbar overlays it
   instead of sitting above it unless something else clears the space.
   .padding-section-large's own top padding is rem-based and tracks the
   site's fluid type scale closely enough that, on its own, it lands within
   a few px of the navbar's own (also-shrinking) height across nearly the
   entire <=991px range — measured with no extra padding at all, the gap
   between navbar and first content is 0px (tight but not overlapping) from
   320px up to 991px, with one narrow exception: 480-580px, where it dips
   up to 8px short (navbar briefly taller relative to the fluid padding
   right around where the mobile menu button appears). A flat 24px buffer
   covers that dip with room to spare and gives a bit of intentional
   breathing room everywhere else, without reintroducing the ~100-124px of
   dead space a much larger fixed value produced (confirmed on /contact,
   /subscribe, and the legal pages, at both phone and iPad widths — "a lot
   of padding at the top of the image"). Fixed px (not rem) on purpose so
   it doesn't shrink away at the narrowest widths the way the dip does. */
@media screen and (max-width: 991px) {
  .main-wrapper.no-hero {
    padding-top: 24px;
  }
}

/* At 768-991px, .padding-section-large's own fluid top padding has grown
   to 74-96px on its own — comfortably more than the 52-72px tall navbar in
   that range on its own, so no extra buffer is needed at all here. */
@media screen and (min-width: 768px) and (max-width: 991px) {
  .main-wrapper.no-hero {
    padding-top: 0;
  }
}

/* Keep this css code to improve font quality (was a separate <style> tag in <head>) */
* {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -o-font-smoothing: antialiased;
}

/* .heading-style-h1 has a margin-top:7rem (112px) that only exists at the
   narrowest breakpoint (<=479px) — a Webflow Designer per-instance tweak,
   almost certainly meant only for the homepage's hero heading (confirmed it
   looks intentional and well-centered there), that leaked into the shared
   class and applies everywhere else reusing it. Reset to 0 for every page
   built on the .no-hero wrapper (everything except the homepage) so this
   heading's spacing comes only from each page's own layout — the success
   pages' 32px wrapper margin, or the Shop/product/Cart pages' own section
   padding — rather than an extra 112px stacked on top. Originally scoped
   only to .new-ga-about_about_component (the success pages, where this was
   first reported as "large space between the image and the H1" on
   /subscribe) but the same leak showed up on Shop, the product page, and
   Cart once those existed — broadened to the shared wrapper so it's fixed
   everywhere at once instead of page-by-page. */
@media screen and (max-width: 479px) {
  .main-wrapper.no-hero .heading-style-h1 {
    margin-top: 0;
  }
}

/* Mobile menu dropdown has a border-bottom: 1px solid var(--color-scheme-1--text)
   (black) baked into its base rule, regardless of variant. Invisible on the
   homepage's dark dropdown (black-on-black), but shows up as a stray black
   line along the bottom edge of the light/white dropdown used on every other
   page's navbar (variant="black" -> .text-color-black). Reported on
   /subscribe; scoped to that variant specifically since the dark one isn't
   broken. */
@media screen and (max-width: 991px) {
  .navbar2_menu.is-page-height-tablet.text-color-black {
    border-bottom: none;
  }
}

/* /subscribe's "Order the Current Issue" / "Subscribe Quarterly" buttons:
   stacked vertically and stretched full-width on mobile instead of sitting
   side by side, where they were cramped (their combined natural width
   almost exactly matches the container width at this breakpoint). */
@media screen and (max-width: 767px) {
  .div-block-3 {
    flex-direction: column;
    align-items: stretch;
  }
}

/* .section-2 (wraps the /subscribe buttons and, separately, the
   subscription-success "Manage Subscription" button) gets an extra
   padding-bottom:4rem (64px) tacked on at <=479px, on top of the 64px
   .padding-section-large's own bottom padding already contributes at this
   width — the two stacking is what produced ~2x more whitespace below the
   buttons than above them. .section-2's own base rule is padding-bottom:0;
   resetting back to that at this breakpoint leaves .padding-section-large's
   64px as the only bottom spacing, close to matching the ~56px above. */
@media screen and (max-width: 479px) {
  .section-2 {
    padding-bottom: 0;
  }
}

/* Newsletter signup form (email field + button): the gap before the terms
   text below it felt tight per feedback (1rem, one tier below the site's
   own margin-small (1.5rem) used for comparable spacing elsewhere). Bumped
   one tier up the site's existing spacing scale rather than picking an
   arbitrary value. */
.signup-form-wrapper {
  margin-bottom: 1.5rem;
}

/* Footer redesign per feedback, second pass. First pass split the five
   links (Our Story, Contact, Privacy Policy, Terms & Conditions, Manage
   Your Subscription) into two side-by-side columns — Webflow's original
   markup already grouped them into two separate <div> lists
   (.footer7_link-list, .footer7_legal-list), which is why the two-column
   layout was the easy shape to reach for. Two columns didn't read well in
   practice, and the two lists also had mismatched styling Webflow never
   unified: .footer7_link (Our Story/Contact) is font-weight:600, while
   .footer7_legal-link (the other three) is regular weight, and
   .footer7_legal-link had text-decoration:underline the other list didn't.

   Simplified to a single centered stack: all five links in one column,
   evenly spaced, same regular weight, no underline on any of them. The
   underlying two-<div> structure is untouched (still semantically two
   groups) — .footer7_columns just stacks them instead of placing them
   side by side, and the gap between the two groups matches the gap within
   each group so the seam between them doesn't read as a special break. */
.footer7_columns {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
.footer7_link-list,
.footer7_legal-list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
.footer7_link {
  font-weight: 400;
}
.footer7_legal-link {
  text-decoration: none;
}

/* Homepage "Why a print mag?" section (video left, heading/text/bullets/
   button right): the site CSS only collapses this to a single column at
   <=767px, not across the full tablet range (768-991px) — at tablet widths
   it kept the two-column grid, squeezing the video into a narrow, oddly
   short-and-centered column next to a much taller text column. Extended
   the existing single-column behavior up through the tablet breakpoint per
   feedback, so the video runs full-width (and larger) on top, continuing
   the one-column flow the rest of the page already uses at this width.

   Once single-column, it read as wider than the founder section right
   below it — that section's photo has its own max-width:85% cap (95% at
   <=479px), which .content2_content never had since it wasn't previously a
   single, centered column. Matched those same values here so the two
   sections line up at the same width going down the page. */
@media screen and (max-width: 991px) {
  .content2_content {
    grid-template-columns: 1fr;
    max-width: 85%;
    margin-left: auto;
    margin-right: auto;
  }
}
@media screen and (max-width: 479px) {
  .content2_content {
    max-width: 95%;
  }
}

/* .padding-section-large is used on every page (homepage, subscribe,
   contact, legal pages, success pages) and is symmetric top/bottom at
   every breakpoint (7rem, 6rem, 4rem) except <=479px, where the Webflow
   export only overrides padding-top to 1rem and leaves padding-bottom
   inherited at 4rem from the 767px tier. That's a one-sided per-instance
   tweak, not an intentional design choice, and it's what produced the
   mobile-only gap asymmetry between "Why a print mag?" and "A word from
   the founder" on the homepage (16px above, 64px below — desktop/tablet
   have their own, expected 2x ratio here since those are two independently
   padded sections meeting, not this bug). Matching padding-top back to
   4rem, the same as padding-bottom, fixes it everywhere the class is used
   rather than one-off scoping it to the homepage alone. */
@media screen and (max-width: 479px) {
  .padding-section-large {
    padding-top: 4rem;
  }
}

/* The site's base `li` rule (in genuine-article-magazine.webflow.css) sets
   display:flex + grid-column-gap:1rem, meant for the homepage's icon+text
   checklist items (an <img> and a <p> side by side). .text-rich-text lists
   (privacy-policy, terms-and-conditions) are plain text, not icon lists —
   but they still inherit that flex layout. It's invisible for a list item
   with a single text node, but on privacy-policy's "Personal Information:"
   item, which has a <strong> label followed by separate trailing text,
   flex splits those into two side-by-side items with a 16px gap between
   them, reading like several spaces were typed after the colon and
   wrapping the description in its own indented column instead of flowing
   normally like the "Usage Data:" paragraph right below it. Scoped to
   .text-rich-text so the homepage's icon lists, which rely on the flex
   layout, are untouched. */
.text-rich-text li {
  display: block;
}

/* .section_cta2 ("Join the conversation," directly above the footer) is a
   full-bleed photo, absolutely positioned to cover the section
   (.cta2_background-image-wrapper/.cta2_background-image, both inset:0%).
   The section itself falls back to --color-scheme-1--background, which
   resolves to plain white — normally invisible since the photo covers it
   completely, but a subpixel rounding gap at the image's bottom edge (seen
   on some device pixel ratios) lets a sliver of that white fallback show
   through right against the footer's dark maroon, reading as a stray
   1px white line/stroke between the two sections. Matching the fallback
   to the footer's own background color means any such gap blends in
   instead of showing as a seam. */
.section_cta2 {
  background-color: var(--red-900);
}

/* Hero subheading ("A print-only magazine celebrating the genuine and the
   tangible") wraps with the browser's default greedy line-breaking, which
   on narrow/mobile widths often leaves a long first line and just one or
   two words alone on the second — the same imbalance Webflow's Designer
   exposes as an "is-balanced"/"is-pretty" toggle in its Typography panel.
   That toggle isn't a Webflow-specific mechanism, it's just their UI for
   the standard CSS text-wrap property: text-wrap:balance evens out line
   lengths, which is exactly right for a short heading/subheading like this
   one (browsers only recommend it for a handful of lines — it's too
   expensive to use on full paragraphs, where text-wrap:pretty is the
   equivalent, narrower-supported option instead). Only used once
   (app/page.js's hero), so scoped straight to the class rather than a
   more specific selector. Unsupported browsers just ignore the
   declaration and fall back to normal wrapping — no fallback needed. */
.text-size-large {
  text-wrap: balance;
}

/* Text below a .new-ga-about_about_image-wrapper photo (homepage's "A word
   from the founder" in app/page.js, and the subscribe page's intro in
   app/subscribe/page.js) was capped with the generic .max-width-large
   utility (a fixed 48rem), while the photo above it is capped at 85%/95%
   of the container (from the Webflow export). A fixed cap and a
   percentage cap only happen to line up at wide desktop widths — around
   the tablet range the container itself narrows toward ~48rem, so the
   fixed-width text overtakes the percentage-width photo above it.
   Matching the same percentage here keeps the text exactly as wide as
   the photo at every breakpoint. */
.about-component-text-width {
  width: 100%;
  max-width: 85%;
}
@media screen and (max-width: 479px) {
  .about-component-text-width {
    max-width: 95%;
  }
}

/* Subscribe page testimonials (components/Testimonials.js). The Webflow
   export includes per-piece testimonial classes (new-ga-about_testimonial_*)
   from the same template family as this page's about/hero section, but no
   ready-made grid/card wrapper for arranging several of them together —
   auto-fit keeps this responsive without needing to guess at Webflow's
   per-instance breakpoint overrides, which don't exist for an unplaced
   component like this one. */
/* .text-size-medium's own 2rem padding-bottom was stacking on top of
   .testimonials_section's own deliberate 4rem margin-top right above it,
   producing a ~96px gap between the About the Mag intro paragraph and the
   What Readers Are Saying heading — reported as "too much padding between"
   those two sections. The 4rem is the real, tuned value (see comment on
   Testimonials.js); this paragraph's trailing padding is the redundant
   half, so it's zeroed here specifically rather than touching the shared
   .text-size-medium class (which the homepage and success pages also use,
   without this issue being reported there). */
.about_intro-text {
  padding-bottom: 0;
}
.testimonials_section {
  margin-top: 4rem;
}
.testimonials_grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2rem;
  margin-bottom: 4rem;
}
.testimonials_card {
  background-color: var(--_primitives---colors--neutral-lighter);
  padding: 2rem;
}
/* Override the Webflow piece classes' default center alignment (see the
   .testimonials_grid comment above) — left-justified reads better here,
   lining the quote up with the name/location below it. */
.testimonials_card .new-ga-about_testimonial_content {
  text-align: left;
}
.testimonials_card .new-ga-about_testimonial_rating-wrapper {
  justify-content: flex-start;
  margin-bottom: 1rem;
}
.testimonials_card .new-ga-about_testimonial_client-info {
  margin-top: 1.5rem;
}

/* "Subscribe" hero heading (app/subscribe/page.js) uses the shared h1 style
   for sizing, but its default font-weight (600) reads heavier than the
   "What readers are saying" h2 (500) further down the same page — match
   that weight here instead of changing heading-style-h1 globally, since
   other h1s on the site (homepage hero, success pages) should stay as-is. */
.subscribe-hero_heading {
  font-weight: 500;
}

/* Shop (app/shop/page.js, app/shop/[slug]/page.js) — product catalog backed
   by Sanity. No ready-made Webflow classes for a product grid/card or a
   two-column product detail layout, so these are new. */
.shop_grid {
  display: grid;
  /* Fixed max (not 1fr) so a short grid — even a single product — doesn't
     stretch its card to fill the whole row. auto-fit (not auto-fill) so
     that on a wide screen with few products, the unused tracks collapse
     instead of reserving empty space — otherwise the grid's own box still
     spans the full container width even with only 1-2 cards in it, and
     justify-content below has no empty space left to center into. */
  grid-template-columns: repeat(auto-fit, minmax(220px, 280px));
  /* With unused tracks collapsed, the grid box now shrinks to fit just the
     cards present — center it, so one or two products (or a narrow screen
     where only one column fits) don't end up flush left with empty space
     on the right. */
  justify-content: center;
  gap: 2rem;
  margin-top: 1.5rem;
}
.shop_card {
  display: block;
}
.shop_card-link {
  display: block;
  color: inherit;
  text-decoration: none;
}
.shop_card-action {
  margin-top: 0.75rem;
}
.shop_card-action .button {
  display: block;
  width: 100%;
  text-align: center;
}
/* Square, center-cropped — cover (not contain) so an image never gets
   squeezed to fit; it's cropped to the center of the square instead. */
.shop_card-image {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
}
/* Type chip reads as a kicker label above the title (like a category tag),
   rather than sitting beside the title where it competed with it for the
   same line and felt oddly placed on the right edge of the card. */
.shop_card-type-row {
  margin-top: 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.shop_card-title {
  margin-top: 0.35rem;
  font-weight: 600;
}
.shop_card-volume {
  font-size: 0.78rem;
  color: var(--_primitives---colors--neutral-dark);
}
/* Card Summary is capped at 120 characters in Sanity, but this clamp is
   the real guarantee against overflow — a hard limit on the input can't
   account for how wide individual characters render. */
.shop_card-summary {
  margin-top: 0.35rem;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--_primitives---colors--neutral-dark);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.shop_card-price {
  margin-top: 0.25rem;
  color: var(--_primitives---colors--neutral-darkest);
  opacity: 0.7;
}
.shop_product {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 3rem;
  align-items: center;
}
/* A product with no photo yet (e.g. before one's been uploaded) would
   otherwise sit pinned to the left half of the two-column grid above,
   with a big blank gap where the image belongs — this collapses to one
   centered column instead, sized for reading rather than stretching
   full width. */
.shop_product_no-image {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  text-align: center;
}
.shop_product_no-image .shop_product-details {
  max-width: 36rem;
}
/* .text-size-medium hardcodes text-align:left directly on the description
   paragraphs — same specificity trap fixed for the cart subtotal earlier,
   so the inherited center above doesn't reach them without this. */
.shop_product_no-image .shop_product-details p {
  text-align: center;
}
/* .text-size-medium also hardcodes a 2rem padding-bottom, meant for a
   single standalone block of text elsewhere on the site — stacked across
   several description paragraphs (one per "hard return" in the rich text
   editor) that reads as far too much air between them. */
.shop_product-details .text-size-medium {
  padding-bottom: 0.75em;
}
.shop_product-image {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
}
.shop_product-gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.75rem;
}
.shop_product-gallery-button {
  display: block;
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--_ui-styles---radius--medium);
  background: none;
  cursor: pointer;
  line-height: 0;
}
.shop_product-gallery-button.is-active {
  border-color: var(--color-scheme-1--accent);
}
.shop_product-gallery-image {
  width: 80px;
  height: 80px;
  object-fit: cover;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: calc(var(--_ui-styles---radius--medium) - 2px);
}
.shop_product-details > * + * {
  margin-top: 0.75rem;
}
@media screen and (max-width: 767px) {
  .shop_product {
    grid-template-columns: 1fr;
  }
}


/* Cart (app/cart/page.js) */
.cart_list {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  max-width: 640px;
  margin: 0 auto;
}
.cart_row {
  display: grid;
  grid-template-columns: 4.5rem 1fr auto auto;
  align-items: center;
  gap: 1rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid #00000014;
}
.cart_row-image {
  width: 4.5rem;
  height: 4.5rem;
  object-fit: cover;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--small);
}
.cart_row-quantity {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.cart_row-quantity button {
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid #00000026;
  border-radius: 50%;
  background: none;
  cursor: pointer;
}
.cart_row-remove {
  border: none;
  background: none;
  cursor: pointer;
  text-decoration: underline;
  font-size: 0.875rem;
  opacity: 0.7;
}
/* Same .text-size-medium text-align:left specificity trap as the cart
   subtotal below — a rule that directly targets the element beats an
   inherited value regardless of specificity, so .cart_empty's own
   text-align:center never reached this <p>. */
.cart_empty p {
  text-align: center;
}
/* Sits directly under the cart list, matching its width, so the subtotal
   reads as a summary of that list rather than a stray centered line loose
   in the middle of the much wider page container. Right-aligned so it
   lines up under the rows' own quantity/remove controls on the right. */
.cart_summary {
  max-width: 640px;
  margin: 1.5rem auto 0;
  text-align: right;
}
/* .text-size-medium hardcodes text-align:left directly on the subtotal
   <p> itself — a rule that directly targets an element always wins over
   an inherited value, regardless of specificity, so .cart_summary's
   text-align:right alone never reached it. Needs a rule that also
   directly targets the <p>. Same class also carries a 2rem padding-bottom
   (meant for spacing out body copy elsewhere on the site), which read as
   too much air between the subtotal and the shipping note right under it
   here — cut by half. */
.cart_summary p {
  text-align: right;
}
.cart_summary .text-size-medium {
  padding-bottom: 1rem;
}
@media screen and (max-width: 479px) {
  .cart_row {
    /* auto (not a fixed 3.5rem) so this column sizes to whatever's
       widest between the two things stacked in it — the image and the
       quantity selector below it, the latter of which is wider than the
       image itself. */
    grid-template-columns: auto 1fr;
    grid-template-areas:
      'image details'
      'quantity remove';
    row-gap: 0.75rem;
  }
  .cart_row-image {
    grid-area: image;
    width: 3.5rem;
    height: 3.5rem;
    /* Narrower than the quantity selector below it now that the column
       sizes to fit that selector — center it in the extra space instead
       of sitting flush left, off-center from the selector. */
    justify-self: center;
  }
  .cart_row-details {
    grid-area: details;
  }
  .cart_row-quantity {
    grid-area: quantity;
  }
  .cart_row-remove {
    grid-area: remove;
    justify-self: end;
  }
}

/* Internal production-board admin section (password-gated, noindex). Kept
   visually part of the site (brand fonts/colors) but with its own plain
   card/list chrome rather than reusing marketing-page components. */
.admin-login {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1rem;
  background-color: var(--color-scheme-1--background);
}

.admin-login_card {
  width: 100%;
  max-width: 22rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 2rem;
  background-color: var(--_primitives---colors--white);
  border-radius: var(--_ui-styles---radius--medium);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.admin-login_title {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.admin-login_emblem {
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
}

.admin-login_input {
  padding: 0.75rem 1rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  font-size: 1rem;
}

.admin-login_error {
  color: #c0392b;
  font-size: 0.875rem;
  margin: 0;
}

/* Sidebar shell wrapping every authenticated /admin page (see
   app/admin/(dashboard)/layout.js) — login itself has no sidebar, since
   that route sits outside the (dashboard) group entirely. */
.admin-shell {
  display: flex;
  min-height: 100vh;
  background-color: var(--color-scheme-1--background);
}

/* Pinned to the viewport rather than stretching to match .admin-dashboard's
   height — without this, a long kanban board makes the whole flex row
   (and the sidebar along with it) taller than the screen, pushing the
   footer (Editors cog, Log Out) down the page instead of leaving it
   reachable without scrolling. */
.admin-sidebar {
  flex: 0 0 13rem;
  display: flex;
  flex-direction: column;
  padding: 1.25rem 1rem;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-right: 1px solid var(--_primitives---colors--neutral-light);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.admin-sidebar_title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 400;
  font-size: 0.9rem;
  margin: 0 0 2.25rem 0;
}

.admin-sidebar_emblem {
  width: 1.25rem;
  height: 1.25rem;
  flex: 0 0 auto;
}

.admin-sidebar_nav {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0;
  padding: 0;
  flex: 1;
}

.admin-sidebar_link {
  display: block;
  padding: 0.5rem 0.6rem;
  border-radius: var(--_ui-styles---radius--medium);
  font-size: 0.85rem;
  color: var(--_primitives---colors--neutral-darkest);
  text-decoration: none;
}

.admin-sidebar_link:hover {
  background-color: var(--_primitives---colors--white);
}

.admin-sidebar_link.is-active {
  background-color: var(--_primitives---colors--white);
  font-weight: 600;
  color: var(--color-scheme-1--accent);
}

.admin-sidebar_footer {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--_primitives---colors--neutral-light);
}

.admin-sidebar_user-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.admin-sidebar_user {
  font-size: 0.78rem;
  color: var(--_primitives---colors--neutral-dark);
  margin: 0;
}

/* A settings-style icon, not a primary section — muted like the
   "you're logged in as" line it sits next to, rather than the
   pill-highlight the main nav links get, so it doesn't compete with
   Workspace/Products/Notes for attention. */
.admin-sidebar_settings-icon {
  flex: 0 0 auto;
  color: var(--_primitives---colors--neutral-dark);
  font-size: 1.1rem;
  line-height: 1;
  text-decoration: none;
}

.admin-sidebar_settings-icon:hover,
.admin-sidebar_settings-icon.is-active {
  color: var(--color-scheme-1--accent);
}

.admin-sidebar_logout-button {
  width: 100%;
  padding: 0.5rem 0.6rem;
  font-size: 0.85rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  background: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* Same white-fill hover language as the nav links above it, rather than
   something alarming — logging out isn't a destructive action. */
.admin-sidebar_logout-button:hover {
  background-color: var(--_primitives---colors--white);
  border-color: var(--_primitives---colors--neutral-dark);
}

.admin-dashboard {
  flex: 1;
  min-width: 0;
  padding: 1.5rem;
  font-size: 0.9rem;
}

.admin-dashboard_topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 2rem;
}

.admin-dashboard_topbar h1 {
  margin: 0;
}

.admin-dashboard_topbar-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.products_table-wrap {
  overflow-x: auto;
}

.products_table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.products_table th {
  text-align: left;
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--_primitives---colors--neutral-dark);
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--_primitives---colors--neutral-light);
}

.products_table td {
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--_primitives---colors--neutral-lighter);
  vertical-align: middle;
}

.products_thumb {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--_ui-styles---radius--xsmall);
  background-color: var(--_primitives---colors--neutral-light);
  background-size: cover;
  background-position: center;
}

.products_thumb_empty {
  background-color: var(--_primitives---colors--neutral-lighter);
  border: 1px dashed var(--_primitives---colors--neutral-light);
}

.products_title-link {
  color: inherit;
  font-weight: 600;
  text-decoration: none;
}

.products_title-link:hover {
  color: var(--color-scheme-1--accent);
  text-decoration: underline;
}

.products_subtext {
  display: block;
  font-size: 0.72rem;
  color: var(--_primitives---colors--neutral-dark);
  font-weight: 400;
}

.products_slug {
  font-family: monospace;
  font-size: 0.8rem;
  color: var(--_primitives---colors--neutral-dark);
}

.product-editor {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  max-width: 40rem;
}

/* A quick scratchpad for production ideas that don't belong to any one
   article or issue — cards follow the same visual convention as article
   cards (see .board_card) rather than a plain list, per feedback that
   notes should feel standardized with the rest of the board. */
.notes-board {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 1.1rem;
}

.notes-board_list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.75rem;
}

.note-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;
  background-color: var(--_primitives---colors--white);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 0.75rem 0.9rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.note-card_body,
.note-card_footer {
  align-self: stretch;
}

.note-card_body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  cursor: pointer;
}

.note-card_image {
  width: 100%;
  height: auto;
  border-radius: var(--_ui-styles---radius--xsmall);
  object-fit: cover;
}

.note-card_text {
  font-size: 0.85rem;
  line-height: 1.4;
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

/* Underlined text rather than a pill — a second chip-style pill stacked
   right above the related-issue chip read as two of the same kind of
   thing. Shows just the domain, not the full URL (see formatLinkLabel in
   NotesBoard.js), with an ellipsis as a second line of defense for an
   unusually long hostname. */
.note-card_link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  max-width: 14rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--_primitives---colors--neutral-dark);
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.note-card_link:hover {
  color: var(--color-scheme-1--accent);
}

.note-card_link svg {
  flex: 0 0 auto;
}

.note-card_footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.note-card_footer .board_field-checkbox {
  margin: 0;
  font-size: 0.78rem;
}

.note-card_footer-actions {
  display: flex;
  align-items: center;
  gap: 0.2rem;
}

.note-card_footer-actions .board_edit-icon {
  margin-left: 0;
  font-size: 1rem;
}

.notes-board_list_archived .note-card_text {
  text-decoration: line-through;
  color: var(--_primitives---colors--neutral-dark);
}

.board_notes-delete {
  flex: 0 0 auto;
  border: none;
  background: none;
  color: var(--_primitives---colors--neutral-dark);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.2rem;
}

.board_notes-delete:hover {
  color: #b3261e;
}

/* Production board (kanban-style article/issue assignment). Deliberately
   denser/smaller than the rest of the site's UI — this is an internal
   working tool, not a marketing page, so it should read like a dashboard
   (compact rows, small type) rather than inheriting the site's generous
   editorial spacing. */
.board {
  display: flex;
  gap: 1.1rem;
  align-items: flex-start;
}

.board_pool {
  flex: 0 0 20.5rem;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 1.15rem;
}

.board_issues {
  flex: 1;
  display: flex;
  gap: 0.9rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
}

.board_issue {
  flex: 0 0 20.5rem;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 1.15rem;
  min-height: 6rem;
}

.board_column-title {
  font-size: 0.95rem;
  font-weight: 600;
  margin: 0 0 0.6rem 0;
}

.board_issue-header {
  margin-bottom: 0.5rem;
}

.board_issue-header .board_column-title {
  margin: 0;
}

.board_issue-header-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.3rem;
}

.board_issue-release {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--_primitives---colors--neutral-dark);
}

.board_issue-volume {
  font-size: 0.72rem;
  color: var(--_primitives---colors--neutral-dark);
  margin: 0;
}

.export-issue_warnings {
  font-size: 0.8rem;
  color: var(--_primitives---colors--neutral-dark);
  margin: 0 0 1rem 0;
  padding-left: 1.2rem;
}

.board_lock-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--_primitives---colors--neutral-dark);
}

.board_issue-header-icons {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}

.board_issue-header-icons .board_edit-icon {
  margin-left: 0;
}

.board_edit-icon {
  flex: 0 0 auto;
  margin-left: auto;
  border: none;
  background: none;
  color: var(--_primitives---colors--neutral-dark);
  font-size: 1.35rem;
  cursor: pointer;
  padding: 0.1rem 0.2rem;
  line-height: 1;
}

.board_edit-icon:hover {
  color: var(--color-scheme-1--accent);
}

.board_issue-title-link {
  color: inherit;
  text-decoration: none;
}

.board_issue-title-link:hover {
  color: var(--color-scheme-1--accent);
  text-decoration: underline;
}

.board_add-button {
  padding: 0.4rem 0.75rem;
  font-size: 0.8rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  background: none;
  color: var(--_primitives---colors--neutral-dark);
  cursor: pointer;
}

.board_add-button:hover {
  border-color: var(--color-scheme-1--accent);
  color: var(--color-scheme-1--accent);
}

.board_pool-list,
.board_issue-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-height: 2rem;
}

.board_drop-line {
  height: 3px;
  border-radius: 2px;
  background-color: #5b3aa0;
}

.board_drop-line-vertical {
  flex: 0 0 3px;
  width: 3px;
  align-self: stretch;
  border-radius: 2px;
  background-color: #5b3aa0;
}

.board_card {
  position: relative;
  display: flex;
  gap: 0.7rem;
  background-color: var(--_primitives---colors--white);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 0.9rem 1.8rem 1.55rem 0.95rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.board_card-rail {
  flex: 0 0 auto;
  padding-top: 0.05rem;
}

.board_card-handle {
  display: inline-flex;
  flex-direction: row;
  gap: 3px;
  padding: 0.3rem;
  margin: -0.3rem;
  cursor: grab;
  border-radius: var(--_ui-styles---radius--medium);
}

.board_card-handle:hover {
  background-color: var(--_primitives---colors--neutral-lighter);
}

.board_card-handle:active {
  cursor: grabbing;
}

.board_card-handle span {
  display: block;
  width: 1px;
  height: 0.8rem;
  border-radius: 1px;
  background-color: var(--_primitives---colors--neutral-dark);
}

.board_card-expand {
  position: absolute;
  bottom: 0.35rem;
  right: 0.45rem;
  border: none;
  background: none;
  color: var(--_primitives---colors--neutral-light);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.15rem;
}

.board_card:hover .board_card-expand {
  color: var(--_primitives---colors--neutral-dark);
}

.board_card-expand:hover {
  color: var(--color-scheme-1--accent) !important;
}

.board_card-body {
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

.board_card-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.board_card-title {
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.35;
}

/* Author + type sit right under the title, before anything else — that's
   the "who and what kind of piece is this" line, read before status. */
.board_card-subline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
  font-size: 0.82rem;
}

.board_card-author {
  font-weight: 600;
  color: var(--_primitives---colors--neutral-darkest);
}

.board_card-summary {
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--_primitives---colors--neutral-dark);
  margin-bottom: 0.5rem;
  /* Cards are for a glance, not the full pitch — the complete summary is
     still there (and editable) in the article modal. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.board_card-status-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.82rem;
  color: var(--_primitives---colors--neutral-dark);
}

/* Sits in the title row's top-right corner now, so it reads as prominent
   at-a-glance information (what kind of piece this is) rather than a
   minor footnote — hence the tinted fill instead of a plain outline. */
/* Purple, deliberately outside the red/green "needs work / done" and
   blue/yellow/green status-chip palettes used elsewhere on the board —
   a type chip isn't a state, so it shouldn't read like one. */
/* .board_card-type is the same chip look reused for unrelated "type" chips
   elsewhere (the public shop card's Single Issue/Merchandise chip in
   app/shop/page.js, the admin ProductEditor's product-type chip, and a
   note's related-issue chip in NotesBoard.js) — this class name was
   renamed to board_card-running-header for the article board card
   specifically, but those other three still reference the old name, so
   both selectors are kept here rather than only one. */
.board_card-type,
.board_card-running-header {
  display: inline-block;
  flex: 0 0 auto;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  background-color: #ece4fb;
  color: #5b3aa0;
}

.board_card-select {
  /* text-align/text-align-last on a native <select>'s closed box is
     ignored by Chrome and Safari (only Firefox honors it) — stripping
     the native appearance is what actually makes centering take effect
     everywhere, so this isn't just cosmetic reset. No arrow indicator
     by design — these read as plain chips you click to change. */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  border: none;
  font: inherit;
  text-align: center;
  text-align-last: center;
  cursor: pointer;
  max-width: 100%;
}

/* The default focus ring on a <select> otherwise persists after picking
   an option (until focus moves elsewhere), which reads as a stuck
   selection outline on what's meant to look like a plain chip. */
.board_card-select:focus,
.board_card-select:focus-visible {
  outline: none;
}

.board_card-author-select {
  background-color: transparent;
  font-weight: 600;
  color: var(--_primitives---colors--neutral-darkest);
  padding: 0;
  text-align: left;
  text-align-last: left;
}

.board_card-hidden {
  display: block;
  font-size: 0.78rem;
  font-style: italic;
  margin-bottom: 0.4rem;
}

/* Shared style for the small "does this still need X" glyphs (photos,
   draft text): a glyph with a small check/x badge overlaid in its
   corner — green when done, red when not, so an editor can tell at a
   glance without opening the card. */
.board_card-indicator {
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
}

.board_card-indicator_yes {
  color: #2f8f4e;
}

.board_card-indicator_no {
  color: #c94a3a;
}

.board_card-indicator-badge {
  position: absolute;
  right: -3px;
  bottom: -3px;
  background-color: var(--_primitives---colors--white);
  border-radius: 999px;
}

/* Circular badge showing this article's print position — set intentionally
   from the article editor, never from dragging cards around a column, so
   "?" here just means nobody has committed to a number for it yet. Sits
   alongside the photo/written indicators now, so it's sized to match them
   and uses the same line-art treatment (an outline instead of a filled
   disc) rather than standing out as a bigger, different-styled thing. */
.board_position-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: 1.3rem;
  height: 1.3rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 0 0.15rem;
  border: 1.5px solid currentColor;
}

/* Same green/red as the photo and written indicators, for the same
   "needs work" vs "done" reading — red when no position is set yet,
   green once one is, rather than a neutral gray and the brand accent. */
.board_position-badge_unset {
  color: #c94a3a;
}

.board_position-badge_set {
  color: #2f8f4e;
}

/* Sits alongside the other at-a-glance card indicators — plain text rather
   than an icon since a date needs to actually be read, not just glanced at.
   Same red used for "needs attention" elsewhere once the date has passed. */
.board_card-due {
  font-size: 0.72rem;
  color: var(--_primitives---colors--neutral-dark);
  white-space: nowrap;
}

.board_card-due_overdue {
  color: #c94a3a;
  font-weight: 700;
}

.board_status-badge {
  display: inline-block;
  padding: 0.08rem 0.4rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  text-align: center;
  background-color: var(--_primitives---colors--neutral-light);
  color: var(--_primitives---colors--neutral-darkest);
}

.board_status-badge_in_progress {
  background-color: #dbeafe;
  color: #1e40af;
}

.board_status-badge_complete {
  background-color: #dcefdc;
  color: #1e5c1e;
}

.board_status-badge_in_review {
  background-color: #fde8cc;
  color: #8a5a12;
}

/* Issue statuses reuse the same palette as article statuses, in the same
   progression (gray -> blue -> yellow -> green), rather than inventing
   separate colors for a second status vocabulary. */
.board_issue-status-badge_in_production {
  background-color: #dbeafe;
  color: #1e40af;
}

.board_issue-status-badge_complete {
  background-color: #fde8cc;
  color: #8a5a12;
}

.board_issue-status-badge_printed {
  background-color: #dcefdc;
  color: #1e5c1e;
}

.board_empty {
  font-size: 0.75rem;
  color: var(--_primitives---colors--neutral-dark);
  font-style: italic;
}

.board_modal-overlay {
  position: fixed;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  z-index: 100;
}

.board_modal {
  background-color: var(--_primitives---colors--white);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 1.1rem;
  width: 100%;
  max-width: 22rem;
  max-height: 90vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  font-size: 0.85rem;
}

.board_field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.78rem;
}

.board_field input,
.board_field select,
.board_field textarea {
  padding: 0.35rem 0.5rem;
  font-size: 0.8rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  font-family: inherit;
}

.board_field-checkbox {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

.board_new-author {
  flex-direction: row;
}

.board_link-button {
  background: none;
  border: none;
  color: var(--color-scheme-1--accent);
  font-size: 0.78rem;
  text-align: left;
  cursor: pointer;
  padding: 0;
  width: fit-content;
}

.board_delete-button {
  color: #b3261e;
}

.editors_actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.board_modal-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 0.35rem;
}

.board_modal-actions > div {
  display: flex;
  gap: 0.4rem;
}

.board_modal-actions button {
  font-size: 0.8rem;
  padding: 0.35rem 0.7rem;
}

.board_save-button {
  border: none;
  border-radius: var(--_ui-styles---radius--medium);
  background-color: var(--color-scheme-1--accent);
  color: var(--_primitives---colors--white);
  cursor: pointer;
}

.board_delete-confirm-button {
  background-color: #b3261e;
}

/* A plain word, not a boxed secondary button — Cancel otherwise falls
   back to the browser's default gray, square-cornered button chrome,
   which reads as a second competing action next to Save instead of the
   lower-emphasis "never mind" it's meant to be. */
.board_cancel-button {
  background: none;
  border: none;
  color: var(--_primitives---colors--neutral-dark);
  cursor: pointer;
}

.board_cancel-button:hover {
  color: var(--_primitives---colors--neutral-darkest);
}

/* Article editor modal — title, metadata, draft text, and images all in
   one drill-down modal (wider/taller than the simple create modals). */
.article-editor_modal {
  max-width: 34rem;
  min-height: 32rem;
}

.article-editor_modal select:disabled,
.article-editor_modal textarea:disabled,
.article-editor_modal input:disabled {
  color: var(--_primitives---colors--neutral-dark);
  background-color: var(--_primitives---colors--neutral-lighter);
}

.article-editor_locked-banner {
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 0.6rem 0.8rem;
  font-size: 0.82rem;
  margin-bottom: 0.75rem;
}

.article-editor_readonly-body {
  white-space: pre-wrap;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--_primitives---colors--neutral-dark);
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
  padding: 0.6rem 0.8rem;
  max-height: 12rem;
  overflow-y: auto;
}

.article-editor_row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.article-editor_row .board_field {
  flex: 1;
  min-width: 8rem;
}

.edit-issue_publish-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.7rem;
  background-color: var(--_primitives---colors--neutral-lighter);
  border-radius: var(--_ui-styles---radius--medium);
}

.products_intro {
  margin: -0.75rem 0 1rem 0;
  color: var(--_primitives---colors--neutral-dark);
}

.rich-text_toolbar {
  display: flex;
  gap: 0.3rem;
  margin-bottom: 0.35rem;
}

.rich-text_toolbar button {
  min-width: 1.8rem;
  padding: 0.2rem 0.4rem;
  font-size: 0.75rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  background: none;
  cursor: pointer;
}

.rich-text_toolbar button:hover {
  border-color: var(--color-scheme-1--accent);
  color: var(--color-scheme-1--accent);
}

.rich-text_editable {
  min-height: 10rem;
  max-height: 20rem;
  overflow-y: auto;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  font-size: 0.85rem;
  line-height: 1.55;
}

/* Soft line breaks (Shift+Enter) are stored as a literal "\n" inside the
   span text rather than a separate block — normal white-space collapses
   that character away, so it never actually shows up unless we tell the
   browser to preserve it. */
.rich-text_editable p,
.rich-text_editable h2,
.rich-text_editable h3,
.rich-text_editable blockquote {
  white-space: pre-line;
}

.rich-text_editable p {
  margin: 0 0 0.75em;
}

.rich-text_editable h2 {
  font-size: 1.15rem;
  margin: 0.6em 0 0.4em;
}

.rich-text_editable h3 {
  font-size: 1rem;
  margin: 0.6em 0 0.4em;
}

.rich-text_editable blockquote {
  margin: 0.6em 0;
  padding-left: 0.75em;
  border-left: 2px solid var(--_primitives---colors--neutral-light);
  font-style: italic;
  color: var(--_primitives---colors--neutral-dark);
}

.article-editor_images {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.article-editor_image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.6rem;
}

.article-editor_image-card {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.article-editor_image-card img {
  width: 100%;
  height: 6.5rem;
  object-fit: cover;
  border-radius: var(--_ui-styles---radius--medium);
  background-color: var(--_primitives---colors--neutral-lighter);
}

.article-editor_image-thumb {
  cursor: zoom-in;
}

.lightbox_overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.88);
}

.lightbox_content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  max-width: 90vw;
  max-height: 90vh;
}

.lightbox_content img {
  max-width: 90vw;
  max-height: 82vh;
  object-fit: contain;
  border-radius: var(--_ui-styles---radius--medium);
}

.lightbox_caption {
  color: #fff;
  font-size: 0.85rem;
  text-align: center;
  opacity: 0.85;
  margin: 0;
  max-width: 60ch;
}

.lightbox_close {
  position: absolute;
  top: 1.25rem;
  right: 1.5rem;
  background: none;
  border: none;
  color: #fff;
  font-size: 2.25rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem;
}

.lightbox_nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.1);
  border: none;
  color: #fff;
  font-size: 2.5rem;
  line-height: 1;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lightbox_nav:hover {
  background: rgba(255, 255, 255, 0.2);
}

.lightbox_nav-prev {
  left: 1.5rem;
}

.lightbox_nav-next {
  right: 1.5rem;
}

.lightbox_counter {
  position: absolute;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;
  font-size: 0.8rem;
  opacity: 0.75;
}

.article-editor_image-card input {
  padding: 0.25rem 0.4rem;
  font-size: 0.72rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
}

.article-editor_image-card button {
  align-self: flex-start;
  font-size: 0.7rem;
  color: #b3261e;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.article-editor_dropzone {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  border: 1px dashed var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
  cursor: pointer;
  text-align: center;
}

.article-editor_dropzone.is-dragover {
  border-color: var(--color-scheme-1--accent);
  background-color: var(--_primitives---colors--neutral-lighter);
}

.article-editor_file-input {
  display: none;
}

/* A single attached document (see Draft Attachment in ArticleEditorModal)
   — same dropzone/remove-button language as the image cards above, but a
   flat row instead of a grid card since there's no thumbnail to show. */
.article-editor_file-card {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--_primitives---colors--neutral-light);
  border-radius: var(--_ui-styles---radius--medium);
}

/* The filename link is the one part of this row that can be arbitrarily
   long — truncated with an ellipsis (title attribute carries the full
   name) instead of wrapping, which used to force the size text and
   Remove button to wrap onto their own awkward extra lines too. */
.article-editor_file-card a {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.article-editor_file-card span {
  flex: 0 0 auto;
  white-space: nowrap;
  color: var(--_primitives---colors--neutral-dark);
}

.article-editor_file-card button {
  flex: 0 0 auto;
  font-size: 0.7rem;
  color: #b3261e;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}
