/* ==========================================================================
   ARCHOTYPE UI COMPONENTS
   Shared stylesheet for buttons and the prism-frame modal.

   Include this ONCE per page (enqueue in functions.php, or paste into a
   site-wide stylesheet). It has no page-specific styles in it -- body
   background, layout, etc. all stay in your page templates.

   Requires Orbitron + Open Sans from Google Fonts:
   <link rel="preconnect" href="https://fonts.googleapis.com">
   <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@600;700;800&family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">
   ========================================================================== */

/* ---------- pillar color tokens ----------
   Default (no modifier class) = gray/neutral -- a utility color, not one
   of the 4 narrative pillars. Every pillar, Control included, requires
   its own explicit modifier class on .arch-btn / .arch-modal-frame /
   .arch-card-frame. Nothing is implicitly gold anymore. */

:root {
  --pillar: #9a9a95;
  --pillar-dark: #63625c;
  --pillar-light: #dad8ce;
}

.arch-btn--control,       .arch-modal-frame--control,       .arch-card-frame--control { --pillar: #D4A64A; --pillar-dark: #8a6b28; --pillar-light: #f3d99a; }
.arch-btn--clarity,       .arch-modal-frame--clarity,       .arch-card-frame--clarity { --pillar: #28A9C2; --pillar-dark: #145d6b; --pillar-light: #8fdcea; }
.arch-btn--will,          .arch-modal-frame--will,          .arch-card-frame--will    { --pillar: #38A86B; --pillar-dark: #1c5638; --pillar-light: #8fe0b3; }
.arch-btn--chaos,         .arch-modal-frame--chaos,         .arch-card-frame--chaos   { --pillar: #9D60C4; --pillar-dark: #573269; --pillar-light: #d3a8ec; }
.arch-btn--neutral,       .arch-modal-frame--neutral,       .arch-card-frame--neutral { --pillar: #9a9a95; --pillar-dark: #63625c; --pillar-light: #dad8ce; }

/* ==========================================================================
   BUTTON
   ==========================================================================
   Geometry: for the top chamfer, vertical edge, and bottom chamfer at each
   end to be equal length: cut = height / (2 + sqrt(2)).
   Border uniformity: each nested layer's cut = parent cut - layer_padding *
   (2 - sqrt(2)), so the border/gap/accent-line read the same width on flat
   edges and diagonal corners alike.
   Three sizes ship below (sm / md / lg); default size is lg if no size
   class is added. */

.arch-btn {
  --cut: 16.52px;
  --border-pad: 4px;
  --gap-pad: 4px;
  --line-pad: 1.5px;
  --inner-pad-v: 14px;
  --inner-pad-h: 28px;
  --font-size: 17px;
  --icon-size: 18px;
  --gap: 18px;
  --letter-spacing: 1.5px;
  position: relative;
  display: inline-flex;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 0;
  transform: translateY(0);
  filter: drop-shadow(0 6px 10px rgba(23,20,12,0.16)) drop-shadow(0 2px 4px rgba(23,20,12,0.10));
  transition: transform 0.22s ease, filter 0.22s ease;
}

.arch-btn:hover {
  transform: translateY(-3px);
  filter: drop-shadow(0 12px 18px rgba(23,20,12,0.2)) drop-shadow(0 4px 6px rgba(23,20,12,0.12));
}

/* soft ambient glow on hover, keyed to the button's own pillar color */
.arch-btn::before {
  content: "";
  position: absolute;
  inset: -18px;
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--pillar) 30%, transparent) 0%, transparent 70%);
  filter: blur(14px);
  z-index: -1;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.arch-btn:hover::before { opacity: 1; }

.arch-btn--sm { --cut: 9.08px; --border-pad: 2.5px; --gap-pad: 2px; --line-pad: 1px; --inner-pad-v: 7px; --inner-pad-h: 16px; --font-size: 10px; --icon-size: 11px; --gap: 10px; --letter-spacing: 0.8px; }
.arch-btn--md { --cut: 12.18px; --border-pad: 3px; --gap-pad: 3px; --line-pad: 1.2px; --inner-pad-v: 10px; --inner-pad-h: 22px; --font-size: 13px; --icon-size: 14px; --gap: 14px; --letter-spacing: 1px; }
.arch-btn--lg { --cut: 16.52px; --border-pad: 4px; --gap-pad: 4px; --line-pad: 1.5px; --inner-pad-v: 14px; --inner-pad-h: 28px; --font-size: 17px; --icon-size: 18px; --gap: 18px; --letter-spacing: 1.5px; }

.arch-btn__border {
  min-width: 0;
  padding: var(--border-pad);
  clip-path: polygon(
    var(--cut) 0, calc(100% - var(--cut)) 0,
    100% var(--cut), 100% calc(100% - var(--cut)),
    calc(100% - var(--cut)) 100%, var(--cut) 100%,
    0 calc(100% - var(--cut)), 0 var(--cut)
  );
  background:
    linear-gradient(180deg, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 25%),
    linear-gradient(90deg, var(--pillar-dark) 0%, var(--pillar) 14%, var(--pillar-light) 50%, var(--pillar) 86%, var(--pillar-dark) 100%);
  display: flex;
}

.arch-btn__gap {
  min-width: 0;
  --c1: calc(var(--cut) - (var(--border-pad) * 0.58579));
  padding: var(--gap-pad);
  clip-path: polygon(
    var(--c1) 0, calc(100% - var(--c1)) 0,
    100% var(--c1), 100% calc(100% - var(--c1)),
    calc(100% - var(--c1)) 100%, var(--c1) 100%,
    0 calc(100% - var(--c1)), 0 var(--c1)
  );
  background: #ffffff;
  display: flex;
}

.arch-btn__line {
  min-width: 0;
  --c2: calc(var(--c1) - (var(--gap-pad) * 0.58579));
  padding: var(--line-pad);
  clip-path: polygon(
    var(--c2) 0, calc(100% - var(--c2)) 0,
    100% var(--c2), 100% calc(100% - var(--c2)),
    calc(100% - var(--c2)) 100%, var(--c2) 100%,
    0 calc(100% - var(--c2)), 0 var(--c2)
  );
  background: var(--pillar-light);
  display: flex;
}

.arch-btn__inner {
  min-width: 0;
  --c3: calc(var(--c2) - (var(--line-pad) * 0.58579));
  clip-path: polygon(
    var(--c3) 0, calc(100% - var(--c3)) 0,
    100% var(--c3), 100% calc(100% - var(--c3)),
    calc(100% - var(--c3)) 100%, var(--c3) 100%,
    0 calc(100% - var(--c3)), 0 var(--c3)
  );
  background: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap);
  padding: var(--inner-pad-v) var(--inner-pad-h);
  position: relative;
}

/* inner surface highlight on hover, behind the label -- distinct from
   .arch-btn::before, which is the OUTER ambient blur around the whole
   button. This one sits on the white inner surface itself. Renders
   behind the label/spark automatically: ::before generates as the first
   child, so later real children (label, spark) naturally paint on top
   via normal DOM-order stacking, same technique used for the card's
   glass sheen. */
.arch-btn__inner::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center,
    color-mix(in srgb, var(--pillar-light) 65%, transparent) 0%,
    color-mix(in srgb, var(--pillar-light) 28%, transparent) 45%,
    transparent 75%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.arch-btn:hover .arch-btn__inner::before {
  opacity: 1;
}

.arch-btn__label {
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: var(--font-size);
  letter-spacing: var(--letter-spacing);
  color: #17140c;
  white-space: nowrap;
  position: relative;
}

.arch-btn__spark {
  flex-shrink: 0;
  width: var(--icon-size);
  height: var(--icon-size);
  background: linear-gradient(135deg, var(--pillar-light), var(--pillar-dark));
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
  position: relative;
}

/* ---------- pillar-symbol icons ----------
   A second icon type alongside .arch-btn__spark: simplified thin-line
   versions of each pillar's badge symbol (compass / triangle / check /
   compass-star), built as mask-image SVGs so the fill still comes from
   the button's own background (same trick as .arch-btn__spark), not a
   hardcoded color.

   Usage:
     <span class="arch-btn__icon"></span>
       Auto-picks the icon matching whichever pillar class is on the
       button (Control -> compass, Clarity -> triangle, Will -> check,
       Chaos -> compass-star, Neutral -> spark shape).
     <span class="arch-btn__icon" data-icon="prism"></span>
       Forces a specific icon regardless of the button's own pillar.
       Valid values: compass, prism, check, starcompass, spark.

   .arch-btn__spark and .arch-btn__icon can be mixed freely on the same
   button for multi-icon layouts (see archotype-button-snippet.html for
   left/right/both/none/multiple examples).
*/

.arch-btn__icon {
  flex-shrink: 0;
  width: var(--icon-size);
  height: var(--icon-size);
  background: linear-gradient(135deg, var(--pillar-light), var(--pillar-dark));
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  position: relative;
}

.arch-btn__icon:not([data-icon]) {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M12 2a10 10 0 100 20 10 10 0 000-20zm0 3.2a6.8 6.8 0 110 13.6 6.8 6.8 0 010-13.6z'/%3E%3Cpath d='M12 7l2.4 5-2.4 5-2.4-5z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M12 2a10 10 0 100 20 10 10 0 000-20zm0 3.2a6.8 6.8 0 110 13.6 6.8 6.8 0 010-13.6z'/%3E%3Cpath d='M12 7l2.4 5-2.4 5-2.4-5z'/%3E%3C/svg%3E");
}

.arch-btn--clarity .arch-btn__icon:not([data-icon]) {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l9.5 17h-19z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l9.5 17h-19z'/%3E%3C/svg%3E");
}

.arch-btn--will .arch-btn__icon:not([data-icon]) {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3.5 3.5l4.3 0 4.2 9.2 4.2-9.2 4.3 0-7.4 16.2h-2.2z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3.5 3.5l4.3 0 4.2 9.2 4.2-9.2 4.3 0-7.4 16.2h-2.2z'/%3E%3C/svg%3E");
}

.arch-btn--chaos .arch-btn__icon:not([data-icon]) {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12.0,1.5 13.2,9.0 19.4,4.6 15.0,10.8 22.5,12.0 15.0,13.2 19.4,19.4 13.2,15.0 12.0,22.5 10.8,15.0 4.6,19.4 9.0,13.2 1.5,12.0 9.0,10.8 4.6,4.6 10.8,9.0'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12.0,1.5 13.2,9.0 19.4,4.6 15.0,10.8 22.5,12.0 15.0,13.2 19.4,19.4 13.2,15.0 12.0,22.5 10.8,15.0 4.6,19.4 9.0,13.2 1.5,12.0 9.0,10.8 4.6,4.6 10.8,9.0'/%3E%3C/svg%3E");
}

.arch-btn--neutral .arch-btn__icon:not([data-icon]) {
  -webkit-mask: none;
  mask: none;
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
}

.arch-btn__icon[data-icon="compass"] {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M12 2a10 10 0 100 20 10 10 0 000-20zm0 3.2a6.8 6.8 0 110 13.6 6.8 6.8 0 010-13.6z'/%3E%3Cpath d='M12 7l2.4 5-2.4 5-2.4-5z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M12 2a10 10 0 100 20 10 10 0 000-20zm0 3.2a6.8 6.8 0 110 13.6 6.8 6.8 0 010-13.6z'/%3E%3Cpath d='M12 7l2.4 5-2.4 5-2.4-5z'/%3E%3C/svg%3E");
}

.arch-btn__icon[data-icon="prism"] {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l9.5 17h-19z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l9.5 17h-19z'/%3E%3C/svg%3E");
}

.arch-btn__icon[data-icon="check"] {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3.5 3.5l4.3 0 4.2 9.2 4.2-9.2 4.3 0-7.4 16.2h-2.2z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3.5 3.5l4.3 0 4.2 9.2 4.2-9.2 4.3 0-7.4 16.2h-2.2z'/%3E%3C/svg%3E");
}

.arch-btn__icon[data-icon="starcompass"] {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12.0,1.5 13.2,9.0 19.4,4.6 15.0,10.8 22.5,12.0 15.0,13.2 19.4,19.4 13.2,15.0 12.0,22.5 10.8,15.0 4.6,19.4 9.0,13.2 1.5,12.0 9.0,10.8 4.6,4.6 10.8,9.0'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12.0,1.5 13.2,9.0 19.4,4.6 15.0,10.8 22.5,12.0 15.0,13.2 19.4,19.4 13.2,15.0 12.0,22.5 10.8,15.0 4.6,19.4 9.0,13.2 1.5,12.0 9.0,10.8 4.6,4.6 10.8,9.0'/%3E%3C/svg%3E");
}

.arch-btn__icon[data-icon="spark"] {
  -webkit-mask: none;
  mask: none;
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
}

/* ==========================================================================
   MODAL
   ==========================================================================
   --cut here is a fixed design choice (32px), not solved for equal edge
   lengths -- at modal proportions the equal-edge formula produces an
   oversized chamfer since height is much larger and content-driven. */

.arch-backdrop {
  position: fixed;
  inset: 0;
  margin: 0; /* guards against generic theme/page rules like
    ".entry-content > * + * { margin-top: 1.2em }" -- with inset:0 set on
    all sides, a non-auto margin on a fixed element is still honored as an
    offset per spec, which would otherwise shift this off a true
    full-viewport overlay depending on where it happens to sit in the DOM */
  background: rgba(20, 16, 8, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s ease;
  z-index: 100;
}

.arch-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

.arch-modal-frame {
  --cut: 32px;
  --border-pad: 6px;
  --gap-pad: 5px;
  --line-pad: 2px;
  max-width: 480px;
  width: 100%;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  transform: scale(0.94) translateY(10px);
  transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1);
  filter: drop-shadow(0 24px 48px rgba(23,20,12,0.28));
}

.arch-backdrop.is-open .arch-modal-frame {
  transform: scale(1) translateY(0);
}

/* ambient glow halo behind the whole frame, keyed to pillar color */
.arch-modal-frame::before {
  content: "";
  position: absolute;
  inset: var(--ambient-glow-inset, -60px);
  background: radial-gradient(ellipse at center,
    color-mix(in srgb, var(--pillar) 70%, transparent) 0%,
    color-mix(in srgb, var(--pillar-light) 45%, transparent) 40%,
    transparent 75%);
  filter: blur(var(--ambient-glow-blur, 30px));
  z-index: -1;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.arch-backdrop.is-open .arch-modal-frame::before {
  opacity: 1;
}

.arch-modal-frame__border {
  min-width: 0; /* overrides the flex default of min-width:auto, which was
    letting this refuse to shrink below its content's intrinsic width,
    causing it to render wider than its own parent frame on narrow
    viewports */
  padding: var(--border-pad);
  clip-path: polygon(
    var(--cut) 0, calc(100% - var(--cut)) 0,
    100% var(--cut), 100% calc(100% - var(--cut)),
    calc(100% - var(--cut)) 100%, var(--cut) 100%,
    0 calc(100% - var(--cut)), 0 var(--cut)
  );
  background:
    linear-gradient(180deg, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 25%),
    linear-gradient(90deg, var(--pillar-dark) 0%, var(--pillar) 14%, var(--pillar-light) 50%, var(--pillar) 86%, var(--pillar-dark) 100%);
  display: flex;
}

.arch-modal-frame__gap {
  min-width: 0;
  --c1: calc(var(--cut) - (var(--border-pad) * 0.58579));
  padding: var(--gap-pad);
  clip-path: polygon(
    var(--c1) 0, calc(100% - var(--c1)) 0,
    100% var(--c1), 100% calc(100% - var(--c1)),
    calc(100% - var(--c1)) 100%, var(--c1) 100%,
    0 calc(100% - var(--c1)), 0 var(--c1)
  );
  background: #ffffff;
  display: flex;
}

.arch-modal-frame__line {
  min-width: 0;
  --c2: calc(var(--c1) - (var(--gap-pad) * 0.58579));
  padding: var(--line-pad);
  clip-path: polygon(
    var(--c2) 0, calc(100% - var(--c2)) 0,
    100% var(--c2), 100% calc(100% - var(--c2)),
    calc(100% - var(--c2)) 100%, var(--c2) 100%,
    0 calc(100% - var(--c2)), 0 var(--c2)
  );
  background: var(--pillar-light);
  display: flex;
}

.arch-modal-frame__inner {
  min-width: 0;
  --c3: calc(var(--c2) - (var(--line-pad) * 0.58579));
  clip-path: polygon(
    var(--c3) 0, calc(100% - var(--c3)) 0,
    100% var(--c3), 100% calc(100% - var(--c3)),
    calc(100% - var(--c3)) 100%, var(--c3) 100%,
    0 calc(100% - var(--c3)), 0 var(--c3)
  );
  background: linear-gradient(180deg, #ffffff 0%, #fbfbfc 45%, #e7e8ea 100%);
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}

/* glass sheen highlight, top-left of the white interior */
.arch-modal-frame__inner::before {
  content: "";
  position: absolute;
  top: -40%;
  left: -10%;
  width: 120%;
  height: 90%;
  background: linear-gradient(200deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0.3) 35%, transparent 60%);
  pointer-events: none;
}

/* ---------- outer prism corner brackets ----------
   Chamfer-matched open path (horizontal -> 45deg diagonal -> vertical)
   echoing the frame's own --cut angle. This markup is IDENTICAL for every
   modal instance (the geometry is derived from the fixed --cut=32px /
   --border-pad=6px above, not from content), so it can be copy-pasted
   as-is. The four corners live in the HTML snippet, not here -- only the
   positioning/glow rules live in CSS. */

.arch-corner-brackets {
  position: absolute;
  pointer-events: none;
  z-index: 6;
}

/* fully hidden on narrow phone widths -- the fluid scale/offset
   tuning above never converged on a value that looked right across
   the whole 320-420px range (kept overshooting between "sits on the
   border" and "gap too large"). Border, ambient pillar glow, and
   light-leak all stay intact; this only removes the corner accent
   line itself. The fluid scaling above still applies and is still
   useful for the 420-528px tablet-ish range. */
@media (max-width: 420px) {
  .arch-corner-brackets {
    display: none;
  }
}

.arch-corner-brackets svg {
  display: block;
  overflow: visible;
  transform: scale(var(--bracket-scale, 1));
  transform-origin: top left; /* the SVG's own path coordinates are all
    anchored near its top-left regardless of which corner variant this
    is -- the --tr/--bl/--br mirroring happens on the WRAPPER div
    separately, so this stays consistent across all four */
  filter: blur(2px) drop-shadow(0 0 4px rgba(255,255,255,1)) drop-shadow(0 0 9px rgba(255,255,255,1)) drop-shadow(0 0 16px rgba(255,255,255,1)) drop-shadow(0 0 24px rgba(255,255,255,0.85));
}

.arch-corner-brackets--tl { top: var(--bracket-offset); left: var(--bracket-offset); }
.arch-corner-brackets--tr { top: var(--bracket-offset); right: var(--bracket-offset); transform: scaleX(-1); }
.arch-corner-brackets--bl { bottom: var(--bracket-offset); left: var(--bracket-offset); transform: scaleY(-1); }
.arch-corner-brackets--br { bottom: var(--bracket-offset); right: var(--bracket-offset); transform: scale(-1, -1); }

/* at narrow viewports the modal frame itself shrinks (correctly, via its
   own max-width:480px/width:100%), but this fixed -30px bracket offset
   doesn't scale down with it -- proportionally it's subtle on a 480px
   desktop modal, but on a ~272px mobile modal it's large enough to push
   the brackets past the actual browser edge, not just past the frame's
   own edge (which is the intended decorative effect). Shrinking the
   offset below this width keeps the same accent, just contained. */
/* Bracket offset, glow, ambient halo, and light-leak all scale
   CONTINUOUSLY with viewport width via clamp(), rather than snapping
   between two fixed states at one breakpoint. A discrete media query
   was leaving these at full desktop values all the way down to 420px
   (even though the frame itself -- width:100%; max-width:480px -- has
   been shrinking continuously the whole time), then jumping abruptly.
   These clamp() formulas are calibrated so each value hits its mobile
   number at a 320px viewport and its desktop number at 528px (the
   point where the frame's own width hits its 480px cap, accounting
   for the backdrop's 24px padding on each side: 480+24+24=528). */
.arch-modal-frame {
  --bracket-offset: clamp(-30px, calc(-9.69px - 3.846vw), -22px);
  --bracket-scale: clamp(0.45, calc(0.45 + ((100vw - 320px) / 208px) * 0.55), 1);
  --ambient-glow-inset: clamp(-60px, calc(16.15px - 14.42vw), -30px);
  --ambient-glow-blur: clamp(15px, calc(-8.08px + 7.21vw), 30px);
  --lightleak-blur: clamp(9px, calc(-4.85px + 4.33vw), 18px);
}

/* ---------- inner corner accents (top-left + bottom-right only) ----------
   Same chamfer-matched 3-segment shape, offset INWARD from the frame's
   real chamfer (--c3) rather than outward like the outer brackets, since
   this lives inside the clipped .arch-modal-frame__inner. */

.arch-modal__inner-bracket {
  position: absolute;
  pointer-events: none;
}
.arch-modal__inner-bracket--tl { top: 0; left: 0; }
.arch-modal__inner-bracket--br { bottom: 0; right: 0; transform: scale(-1, -1); }

/* ---------- light leaks ---------- */

.arch-modal-frame__lightleak {
  position: absolute;
  mix-blend-mode: screen;
  filter: blur(var(--lightleak-blur, 18px));
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s ease;
  z-index: 4;
  animation-play-state: paused;
}

.arch-modal-frame__lightleak--tl {
  top: -70px;
  left: -70px;
  width: 280px;
  height: 280px;
  background: radial-gradient(ellipse at 35% 35%, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.3) 35%, transparent 65%);
  animation: arch-leak-drift-tl 14s ease-in-out infinite;
}

.arch-modal-frame__lightleak--br {
  bottom: -55px;
  right: -55px;
  width: 190px;
  height: 190px;
  background: radial-gradient(ellipse at 65% 65%, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0.22) 35%, transparent 65%);
  animation: arch-leak-drift-br 17s ease-in-out infinite;
}

@keyframes arch-leak-drift-tl {
  0%   { transform: translate(0, 0) scale(1); }
  30%  { transform: translate(34px, 24px) scale(1.35); }
  55%  { transform: translate(-20px, 38px) scale(0.75); }
  80%  { transform: translate(16px, -26px) scale(1.15); }
  100% { transform: translate(0, 0) scale(1); }
}

@keyframes arch-leak-drift-br {
  0%   { transform: translate(0, 0) scale(1); }
  35%  { transform: translate(-26px, -30px) scale(1.4); }
  60%  { transform: translate(24px, 16px) scale(0.7); }
  85%  { transform: translate(-12px, 28px) scale(1.15); }
  100% { transform: translate(0, 0) scale(1); }
}

.arch-backdrop.is-open .arch-modal-frame__lightleak--tl,
.arch-backdrop.is-open .arch-modal-frame__lightleak--br {
  animation-play-state: running;
}

.arch-backdrop.is-open .arch-modal-frame__lightleak--tl { opacity: 0.6; }
.arch-backdrop.is-open .arch-modal-frame__lightleak--br { opacity: 0.45; }

/* ---------- modal content ---------- */

.arch-modal {
  padding: 44px 44px 40px;
  position: relative;
  z-index: 1;
}

.arch-modal__close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 28px;
  height: 28px;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.arch-modal__close::before,
.arch-modal__close::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 2px;
  background: var(--pillar-dark);
  border-radius: 1px;
  transition: background 0.2s ease;
}
.arch-modal__close::before { transform: rotate(45deg); }
.arch-modal__close::after { transform: rotate(-45deg); }
.arch-modal__close:hover::before,
.arch-modal__close:hover::after { background: var(--pillar); }

.arch-modal__eyebrow {
  font-family: 'Orbitron', sans-serif;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 3px;
  color: var(--pillar);
  text-transform: uppercase;
  margin: 0 0 10px;
}

.arch-modal__title {
  font-family: 'Orbitron', sans-serif;
  font-weight: 800;
  font-size: clamp(18px, 6vw, 26px);
  letter-spacing: 1px;
  color: #333333;
  margin: 0 0 14px;
  line-height: 1.25;
  overflow-wrap: break-word;
}

.arch-modal__body {
  font-family: 'Open Sans', sans-serif;
  font-size: 15px;
  line-height: 1.6;
  color: #4a463e;
  margin: 0 0 28px;
}

.arch-modal__form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.arch-modal__input {
  font-family: 'Open Sans', sans-serif;
  font-size: 14px;
  padding: 14px 18px;
  border: 1.5px solid #e4ddc9;
  border-radius: 4px;
  outline: none;
  color: #17140c;
  transition: border-color 0.2s ease;
}
.arch-modal__input:focus {
  border-color: var(--pillar);
}

.arch-modal__input:-webkit-autofill,
.arch-modal__input:-webkit-autofill:hover,
.arch-modal__input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0px 1000px #ffffff inset;
  -webkit-text-fill-color: #17140c;
  caret-color: #17140c;
  transition: background-color 5000s ease-in-out 0s;
}

.arch-modal__form .arch-btn {
  align-self: flex-start;
}

/* ==========================================================================
   CARD
   ==========================================================================
   Same layered-border construction as the modal (border -> white gap ->
   thin accent line -> white interior, same uniform-thickness math), but a
   static in-page element -- no backdrop, no open/close JS, no fixed
   positioning. Meant for a row of pillar cards (Control / Clarity / Will /
   Chaos / Neutral).

   --cut here is smaller than the modal's (20px vs 32px) since the card is
   a narrower surface -- same "fixed design choice, not equal-edge" logic
   as the modal's own chamfer.
*/

.arch-card-frame {
  --cut: 20px;
  --border-pad: 4px;
  --gap-pad: 3px;
  --line-pad: 1.5px;
  --channel-color-opacity: 20%;
  --channel-edge-blur: 10px;
  --channel-speed: 5s;
  position: relative;
  display: inline-flex;
  flex: 1 1 280px;
  min-width: 240px;
  isolation: isolate;
}

.arch-card-frame::before {
  content: "";
  position: absolute;
  inset: -34px;
  background: radial-gradient(ellipse at center,
    color-mix(in srgb, var(--pillar) 85%, transparent) 0%,
    color-mix(in srgb, var(--pillar-light) 60%, transparent) 40%,
    transparent 75%);
  filter: blur(24px);
  z-index: -1;
}

/* ---------- clickable variant ----------
   Add this modifier when the card is wrapped in a link/button (i.e. it
   actually does something on click). Plain informational cards should
   NOT get this -- the lift + shadow implies interactivity. */

.arch-card-frame--clickable {
  cursor: pointer;
  text-decoration: none !important;
  color: inherit;
  transform: translateY(0) translateZ(0);
  filter: drop-shadow(0 6px 10px rgba(23,20,12,0.14)) drop-shadow(0 2px 4px rgba(23,20,12,0.08));
  transition: transform 0.22s ease, filter 0.22s ease;
}

.arch-card-frame--clickable,
.arch-card-frame--clickable * {
  text-decoration: none !important;
}

.arch-card-frame--clickable:hover {
  transform: translateY(-10px) translateZ(0);
  filter: drop-shadow(0 22px 32px rgba(23,20,12,0.24)) drop-shadow(0 8px 12px rgba(23,20,12,0.14));
}

.arch-card-frame__border {
  padding: var(--border-pad);
  clip-path: polygon(
    var(--cut) 0, calc(100% - var(--cut)) 0,
    100% var(--cut), 100% calc(100% - var(--cut)),
    calc(100% - var(--cut)) 100%, var(--cut) 100%,
    0 calc(100% - var(--cut)), 0 var(--cut)
  );
  background:
    linear-gradient(180deg, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 25%),
    linear-gradient(90deg, var(--pillar-dark) 0%, var(--pillar) 14%, var(--pillar-light) 50%, var(--pillar) 86%, var(--pillar-dark) 100%);
  display: flex;
  width: 100%;
}

.arch-card-frame__gap {
  --c1: calc(var(--cut) - (var(--border-pad) * 0.58579));
  padding: var(--gap-pad);
  clip-path: polygon(
    var(--c1) 0, calc(100% - var(--c1)) 0,
    100% var(--c1), 100% calc(100% - var(--c1)),
    calc(100% - var(--c1)) 100%, var(--c1) 100%,
    0 calc(100% - var(--c1)), 0 var(--c1)
  );
  background: #ffffff;
  display: flex;
  width: 100%;
}

.arch-card-frame__line {
  --c2: calc(var(--c1) - (var(--gap-pad) * 0.58579));
  padding: var(--line-pad);
  clip-path: polygon(
    var(--c2) 0, calc(100% - var(--c2)) 0,
    100% var(--c2), 100% calc(100% - var(--c2)),
    calc(100% - var(--c2)) 100%, var(--c2) 100%,
    0 calc(100% - var(--c2)), 0 var(--c2)
  );
  background: var(--pillar-light);
  display: flex;
  width: 100%;
}

.arch-card-frame__inner {
  --c3: calc(var(--c2) - (var(--line-pad) * 0.58579));
  clip-path: polygon(
    var(--c3) 0, calc(100% - var(--c3)) 0,
    100% var(--c3), 100% calc(100% - var(--c3)),
    calc(100% - var(--c3)) 100%, var(--c3) 100%,
    0 calc(100% - var(--c3)), 0 var(--c3)
  );
  background: linear-gradient(180deg, #ffffff 0%, #fbfbfc 45%, #e7e8ea 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  position: relative;
}

/* glass sheen highlight, top-left of the white interior -- same treatment
   as the modal's own inner surface. clip-path on this element already
   contains it to the chamfered shape (clip-path clips generated content
   too, not just the background), so no overflow:hidden needed. */
.arch-card-frame__inner::before {
  content: "";
  position: absolute;
  top: -40%;
  left: -10%;
  width: 120%;
  height: 90%;
  background: linear-gradient(200deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0.3) 35%, transparent 60%);
  pointer-events: none;
}

.arch-card {
  padding: 26px 20px 32px 20px;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
}

/* circular badge, half-overlapping the card's top edge */
/* ---------- badge (WIP -- iterating with Scotty, see chat) ----------
   Pure image, no border/circle chrome of its own -- whatever image URL
   is supplied IS the visual, unlike the button icon system (which uses
   CSS mask-image auto-icons). Explicitly NOT reusing that system here
   per instruction. */

.arch-card__badge {
  position: absolute;
  top: -81px;
  left: 50%;
  transform: translateX(-50%);
  width: 162px;
  height: 162px;
  z-index: 1;
  filter: drop-shadow(0 3px 5px rgba(23,20,12,0.18));
}

.arch-card__badge img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  background: none; /* defensive override -- protects against stray global
    "img" styling from the theme or elsewhere (e.g. a leftover
    .single-entry-content img rule), regardless of source or load order */
  border-radius: 0;
  padding: 0;
}

.arch-card__title {
  font-family: 'Orbitron', sans-serif;
  font-weight: 800;
  font-size: 20px;
  letter-spacing: 2px;
  color: #333333;
  margin: 0 0 4px;
}

.arch-card__subtitle {
  font-family: 'Orbitron', sans-serif;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 2px;
  color: var(--pillar);
  text-transform: uppercase;
  margin: 0 0 20px;
}

/* image placeholder -- swap the background for real artwork per card */
.arch-card__image {
  display: none;
  width: calc(100% + 40px);
  margin-left: -20px;
  margin-right: -20px;
  aspect-ratio: 4 / 3;
  clip-path: polygon(
    0 0, 100% 0, 100% 100%,
    calc(50% + 76px) 100%, calc(50% + 66px) calc(100% - 10px),
    calc(50% - 66px) calc(100% - 10px), calc(50% - 76px) 100%,
    0 100%
  );
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 18%);
  mask-image: linear-gradient(to bottom, transparent 0%, black 18%);
  background: #e3e3e1;
  margin-bottom: 20px;
  position: relative;
  overflow: hidden;
  border-top: 1px solid white; /* covers the sub-pixel rendering gap that
    could appear at the mask's top edge during the card's hover-lift
    animation -- doesn't fix the underlying cause, just visually masks
    it, which is a standard, reliable approach for this class of
    animation artifact. Confirmed fix, found via testing. */
  transform: translateZ(0); /* promotes THIS masked element to its own
    stable GPU layer -- the parent card's own translateZ(0) wasn't
    enough, since this element owns the expensive mask-image operation
    and needs its own layer stability during the ancestor's transform */
}

/* hover-zoom photo layer -- lives INSIDE .arch-card__image (which owns the
   shape: clip-path, mask, size, and never moves). This is the layer that
   actually scales on hover, clipped cleanly to that fixed outer shape.
   Set the background-image on THIS element now, not on .arch-card__image
   itself -- scaling the shape-owning element directly would distort the
   notch/bevel geometry along with the photo. */
.arch-card__image-photo {
  position: absolute;
  inset: -2px; /* small permanent buffer beyond the visible edge -- absorbs
    sub-pixel rounding gaps that can appear briefly during the scale
    transition, since the outer element's clip-path/mask/overflow already
    define the real visible boundary regardless of this extra margin */
  background-size: cover;
  background-position: center;
  transition: transform 0.4s ease;
  transform: scale(1);
}
.arch-card-frame:hover .arch-card__image-photo {
  transform: scale(1.1);
}

.arch-card__body {
  font-family: 'Open Sans', sans-serif;
  font-size: 13px;
  line-height: 1.6;
  color: #4a463e;
  margin: 0;
}

/* ---------- inner corner accents (top-left + bottom-right only) ----------
   Same construction as the modal's inner brackets: a thin, neutral gray
   line offset INWARD from the card's real chamfer (--c3 on
   .arch-card-frame__inner), using diagonal_cut = c3 + gap*sqrt(2) so the
   perpendicular gap from the real border is uniform on all three
   segments. Positive coordinates only, since this lives inside the
   clipped .arch-card-frame__inner. */

.arch-card__inner-bracket {
  position: absolute;
  pointer-events: none;
  z-index: 3;
}
.arch-card__inner-bracket--tl { top: 0; left: 0; }
.arch-card__inner-bracket--br { bottom: 0; right: 0; transform: scale(-1, -1); }

/* ---------- frosted perimeter ring (WIP -- shape verification phase) ----------
   Lives in the same "gap" as the inner brackets -- between the real card
   edge (--c3) and the g=12 inset where the brackets sit -- but instead of
   empty space, this is where a blur filter will refract whatever's
   underneath (mainly the image, since it's the only thing that reaches
   this band on the left/right edges -- text stays inside the card's own
   padding, well clear of this band).

   Built from 8 independent pieces (4 straight strips + 4 corner wedges)
   rather than one subtracted donut shape -- a "bridge" clip-path attempt
   at a true ring produced a broken/wrong shape (see chat), so this
   decomposition avoids that winding-direction risk entirely. Straight
   strips use plain percentage positioning (calc(100% - Npx)) so they
   scale to any card height automatically; corner wedges are small,
   fixed-size local shapes, same approach as the inner brackets.

   Verified shape confirmed correct (see chat) -- now using the real
   backdrop-filter: blur() glass treatment on all 8 pieces. */

.arch-card__ring-strip {
  position: absolute;
  background: linear-gradient(45deg,
    color-mix(in srgb, #ff1a4d var(--channel-color-opacity), transparent),
    color-mix(in srgb, #ff7a00 var(--channel-color-opacity), transparent),
    color-mix(in srgb, #ffe600 var(--channel-color-opacity), transparent),
    color-mix(in srgb, #00ff8c var(--channel-color-opacity), transparent),
    color-mix(in srgb, #00d9ff var(--channel-color-opacity), transparent),
    color-mix(in srgb, #9500ff var(--channel-color-opacity), transparent),
    color-mix(in srgb, #ff1a4d var(--channel-color-opacity), transparent));
  background-size: 300% 300%;
  animation: arch-card-prism-shift var(--channel-speed) linear infinite alternate;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  filter: blur(var(--channel-edge-blur));
  pointer-events: none;
  z-index: 2;
}
.arch-card__ring-strip--top    { top: 0; left: 15.021px; right: 15.021px; height: 12px; }
.arch-card__ring-strip--bottom { bottom: 0; left: 15.021px; right: 15.021px; height: 12px; }
.arch-card__ring-strip--left   { left: 0; top: 15.021px; bottom: 15.021px; width: 12px; }
.arch-card__ring-strip--right  { right: 0; top: 15.021px; bottom: 15.021px; width: 12px; }

.arch-card__ring-wedge {
  position: absolute;
  width: 20px;
  height: 20px;
  background: linear-gradient(45deg,
    color-mix(in srgb, #ff1a4d var(--channel-color-opacity), transparent),
    color-mix(in srgb, #ff7a00 var(--channel-color-opacity), transparent),
    color-mix(in srgb, #ffe600 var(--channel-color-opacity), transparent),
    color-mix(in srgb, #00ff8c var(--channel-color-opacity), transparent),
    color-mix(in srgb, #00d9ff var(--channel-color-opacity), transparent),
    color-mix(in srgb, #9500ff var(--channel-color-opacity), transparent),
    color-mix(in srgb, #ff1a4d var(--channel-color-opacity), transparent));
  background-size: 300% 300%;
  animation: arch-card-prism-shift var(--channel-speed) linear infinite alternate;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  filter: blur(var(--channel-edge-blur));
  pointer-events: none;
  z-index: 2;
}
.arch-card__ring-wedge--tl { top: 0; left: 0; clip-path: polygon(15.021px 0, 19.99px 12px, 12px 19.99px, 0 15.021px); }
.arch-card__ring-wedge--tr { top: 0; right: 0; clip-path: polygon(calc(20px - 15.021px) 0, calc(20px - 19.99px) 12px, 8px 19.99px, 20px 15.021px); }
.arch-card__ring-wedge--bl { bottom: 0; left: 0; clip-path: polygon(15.021px 20px, 19.99px 8px, 12px calc(20px - 19.99px), 0 calc(20px - 15.021px)); }
.arch-card__ring-wedge--br { bottom: 0; right: 0; clip-path: polygon(calc(20px - 15.021px) 20px, calc(20px - 19.99px) 8px, 8px calc(20px - 19.99px), 20px calc(20px - 15.021px)); }

/* WIP -- corner seams not yet phase-matched, so the rainbow doesn't flow
   perfectly continuously around the perimeter yet, same as the modal's
   prism brackets needed calibration between mirrored corners. */
@keyframes arch-card-prism-shift {
  0%   { background-position: 0% 0%; }
  100% { background-position: 100% 100%; }
}

/* ==========================================================================
   UTILITIES
   ========================================================================== */

/* visually hidden but still readable by screen readers -- standard
   accessible-hiding pattern, used e.g. for form labels that are covered
   visually by a placeholder */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}