/*
 * Run Logic - Main Stylesheet
 * Repository: https://github.com/noustelos/run_logic
 * Based on CodePen: https://codepen.io/ikrprojects/pen/KwgGBRp
 */

/* ========================================
   Base Styles & Imports
   ======================================== */
@import url('https://fonts.googleapis.com/css2?family=Big+Shoulders+Display:wght@600;700;800&family=Source+Code+Pro:ital,wght@0,400..600;1,400..600&display=swap');

* {
    box-sizing: border-box;
}

/* ========================================
   Brand Badge
   ======================================== */
.brand-badge {
    display: block;
    position: relative;
    text-align: center;
    padding: 12px 0;
    z-index: 1;
}

.brand-badge a {
    font-family: "Source Code Pro", monospace;
    font-size: 14px;
    font-weight: 400;
    color: #ff8c42;
    text-decoration: none;
    transition: color 0.3s ease;
}

.brand-badge a:hover {
    color: #ffa580;
}

.badge-mark {
    color: #ff8c42;
    opacity: 0.7;
}

.brand-badge a:hover .badge-mark {
    opacity: 1;
}

/* ========================================
   Top Bar
   ======================================== */
.top-bar {
    position: relative;
    width: 100%;
    padding: 1rem 2rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    z-index: 9999;
}

html, body {
    width: 100vw;
    margin: 0;
    padding: 0px;
    overflow-x: clip;
    overscroll-behavior: none;
}

body {
    --tabletVerticaloffset: 0px;
    background: #0f0f0f;
    font-size: 1.2rem;
    font-weight: 400;
    font-style: normal;
    color: #FFFFFF;
}

/* ========================================
   Hero
   ======================================== */
/* Fixed height on purpose: #svgPaths reaches up into this block with a
   hard-coded offset, so the hero must not resize with the viewport. */
.hero {
    position: relative;
    height: 510px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    z-index: 2;
}

/* Full bleed, no frame - the lines read as rising out of the page itself
   rather than escaping from a box. */
.hero-texture {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
}

#heroWaves path {
    fill: none;
    stroke: #ff8c42;
    stroke-width: 1;
}

/* ---- Wave motion (shared by the hero band and the finale texture) ----
   Drift slides one full wavelength; because the wave is periodic, the loop
   closes with no seam. Sway and swell run on the inner group at unrelated
   periods, so the three rhythms never realign. */
.wave-drift {
    animation-name: waveDrift;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}

.wave-sway {
    animation-name: waveSway, waveSwell;
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
}

@keyframes waveDrift {
    from { transform: translateX(0); }
    to   { transform: translateX(var(--drift)); }
}

@keyframes waveSway {
    from { transform: translateY(calc(var(--sway) * -1)); }
    to   { transform: translateY(var(--sway)); }
}

@keyframes waveSwell {
    from { opacity: 1; }
    to   { opacity: 0.45; }
}

@media (prefers-reduced-motion: reduce) {
    .wave-drift,
    .wave-sway {
        animation: none;
    }
}

/* Dissolve at every edge so the band has nowhere it visibly stops. */
.hero-texture {
    -webkit-mask-image: radial-gradient(ellipse 62% 74% at 50% 44%,
                        #000 0%, rgba(0, 0, 0, 0.6) 52%, transparent 100%);
    mask-image: radial-gradient(ellipse 62% 74% at 50% 44%,
                #000 0%, rgba(0, 0, 0, 0.6) 52%, transparent 100%);
}

.hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: radial-gradient(ellipse 36% 32% at 50% 40%,
                rgba(15, 15, 15, 0.85) 0%, rgba(15, 15, 15, 0.45) 55%, transparent 80%);
}

.hero-content {
    position: relative;
    z-index: 1;
    text-align: center;
    padding: 0 20px;
    /* Sits above centre: the lines fan out of the space left below it. */
    transform: translateY(-42px);
    opacity: 0;
    animation: heroIn 1.8s cubic-bezier(0.16, 0.78, 0.3, 1) 0.4s forwards;
}

.hero-title {
    margin: 0;
    /* The cards spell HTML with a drawn path, not a typeface: narrow, heavy,
       flat terminals (the H is 44x109 units). Big Shoulders Display is the
       closest match on the same axis - condensed industrial grotesque. */
    font-family: "Big Shoulders Display", "Anton", sans-serif;
    font-weight: 700;
    font-size: clamp(58px, 10.5vw, 126px);
    line-height: 0.92;
    letter-spacing: 0.012em;
    text-transform: uppercase;
    /* Hollow letters with a thin orange edge - the same treatment the cards
       get from #htmlMask2, which reveals the gradient only as a ring. */
    color: transparent;
    -webkit-text-stroke: 2px #ff8c42;
    text-stroke: 2px #ff8c42;
    /* text-shadow still draws from the glyph shape even with a transparent
       fill, so this reads as a faint bloom inside and around the outline. */
    text-shadow:
        0 0 16px rgba(255, 102, 0, 0.30),
        0 0 44px rgba(255, 102, 0, 0.15);
    animation: titleSettle 2.1s cubic-bezier(0.16, 0.78, 0.3, 1) 0.4s backwards;
}

/* Tracking closes as the block fades up. Declared here rather than on
   .hero-content, whose value the children override. */
@keyframes titleSettle {
    from { letter-spacing: 0.26em; }
    to   { letter-spacing: 0.012em; }
}

.hero-caret {
    display: inline-block;
    width: 0.4em;
    height: 0.05em;
    margin-left: 0.14em;
    vertical-align: 0.02em;
    border-radius: 1px;
    background-color: #ff8c42;
    box-shadow: 0 0 14px rgba(255, 102, 0, 0.45);
    animation: caretBreathe 3.4s ease-in-out infinite;
}

.hero-tag {
    margin: 22px 0 0;
    font-family: "Source Code Pro", monospace;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: 0.14em;
    color: rgba(255, 140, 66, 0.5);
}

@keyframes heroIn {
    from {
        opacity: 0;
        transform: translateY(-24px);
        filter: blur(10px);
    }
    to {
        opacity: 1;
        transform: translateY(-42px);
        filter: blur(0);
    }
}

/* A slow swell instead of a hard blink - present, but never nagging. */
@keyframes caretBreathe {
    0%, 100% { opacity: 0.18; }
    50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .hero-content,
    .hero-title,
    .hero-caret {
        animation: none;
    }

    .hero-content {
        opacity: 1;
    }
}

@media (max-width: 575px) {
    .hero {
        height: 440px;
    }
}

/* ========================================
   Main Container
   ======================================== */
main {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    width: 100%;
    max-width: 740px;
    height: 5350px;
    padding: 0px;
    margin-left: auto;
    margin-right: auto;
    visibility: visible;
    opacity: 0;
    overscroll-behavior: none;
    transition: opacity 0.5s ease;
}

main.js-ready {
    opacity: 1;
}

/* ========================================
   Cards Container
   ======================================== */
.cards {
    display: block;
    width: 300px;
    position: absolute;
    top: 0px;
    z-index: 10;
}

@media (min-width: 576px) {
    .cards {
        transform: translateX(4vw);
    }
}

/* ========================================
   Card Wrapper
   ======================================== */
.cardWrapper {
    display: block;
    position: relative;
    width: 300px;
    height: 450px;
    border-radius: 20px;
    margin-top: 25px;
    margin-bottom: 25px;
    overflow: clip;
}

.cardWrapper::before {
    position: absolute;
    content: " ";
    display: block;
    z-index: 0;
    width: inherit;
    height: inherit;
    border-radius: inherit;
    background-color: rgba(255, 102, 0, 0.08);
    backdrop-filter: blur(8px);
}

.cardWrapper::after {
    position: absolute;
    left: 0px;
    top: 0px;
    z-index: 0;
    content: " ";
    display: block;
    width: inherit;
    height: 450px;
    border-radius: 20px;
    background-image: url('data:image/svg+xml,<svg width="300" height="450" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="cl2" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1" gradientTransform="rotate(45)"><stop offset="20%" stop-color="%23ff6600"/><stop offset="45%" stop-color="%23ff8c42"/><stop offset="65%" stop-color="%23ffa580"/><stop offset="85%" stop-color="%23ffbb99"/></linearGradient></defs><path fill="url(%23cl2)" stroke="none" d="M 20,0C 9,0 0,9 0,20v 410c 0,11 9,20 20,20h 130 130c 11,0 20,-9 20,-20V 20C 300,9 291,0 280,0Zm 1,1h 161l 95,2c 12,1 19,10 19,20L 299,175v 254c 0,11 -9,20 -20,20H 118l -95,-3c -10,0 -20,-8 -20,-20L 1,275V 22C 1,11 10,1 21,1Z" /></svg>');
    filter: blur(1px) saturate(1.2) brightness(1.2);
    opacity: 0.85;
}

@media (min-width: 576px) {
    .cardWrapper:nth-child(odd) {
        transform: translateX(6vw);
    }
    .cardWrapper:nth-child(even) {
        transform: translateX(-3vw);
    }
}

/* ========================================
   Card Component
   ======================================== */
.card {
    display: block;
    width: 300px;
    height: 450px;
    border-radius: 20px;
    background-color: #1a120f;
    background: radial-gradient(closest-corner, #120c08 10%, #1a120f 90%),
    linear-gradient(50deg, #281c12 0%, transparent 25%, transparent 75%, #120c08 100%);
    color: #FFFFFF;
    position: relative;
    mask-composite: subtract;
}

.card::before {
    position: absolute;
    left: 0px;
    top: 0px;
    z-index: 0;
    display: block;
    content: "";
    width: 300px;
    height: 450px;
    background: linear-gradient(-45deg, #ff6600 20%, #ff8c42, #ffa580, #cc5500 70%);
    opacity: 0.45;
}

.card foreignobject {
    color: #FFF;
}

.card header,
.card code {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 310px;
    padding: 20px;
    text-overflow: clip;
    background-image: linear-gradient(-45deg, #ff8c42 20%, #ffb366, #ff9955, #ff6600 70%);
    background-clip: text;
    color: transparent;
    text-shadow: none;
    text-align: left;
    filter: brightness(1.1);
    margin-right: auto;
}

.card header.type {
    font-family: "Source Code Pro", monospace;
    font-optical-sizing: auto;
    font-style: normal;
    font-size: 34px;
    font-weight: 400;
}

.card code {
    font-size: 14px;
    font-weight: 600;
    line-height: 20px;
}

.card code dl {
    width: 260px;
}

.card code dd {
    margin-left: 20px;
}

.card code div[aria-hidden="true"] {
    position: unset !important;
}

/* ========================================
   Card Variants
   ======================================== */
.card {
    mask-image: url(#block), url(#htmlMask);
}

.card::before {
    mask: url(#htmlMask2);
}

/* ========================================
   3D World Background
   ======================================== */
#world3d {
    position: fixed;
    top: var(--tabletVerticaloffset);
    z-index: -1;
    -webkit-perspective: 1000px;
    perspective: 1000px;
    shape-rendering: crispEdges;
    overflow: visible;
    width: 90vw;
    max-width: 1200px;
    padding-top: 5vw;
}

#tablet {
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    transform-origin: 0% 50%;
    -webkit-transform: rotateY(20deg);
    transform: rotateY(20deg);
    position: relative;
    display: block;
    width: 100%;
    height: 150vh;
    padding: 40px;
    padding-left: 140px;
    background-color: #18100c;
    background: linear-gradient(109.61deg, #251810 4.26%, #0f0804 84.84%);
    border-radius: 30px;
    opacity: 0.18;
}

#tablet::before {
    position: absolute;
    left: 120px;
    top: 20px;
    right: 20px;
    bottom: 20px;
    content: "";
    display: block;
    background-color: #1c120c;
    border: thin solid #ff6600;
    border-radius: 20px;
}

/* ========================================
   SVG Paths (Animated Lines)
   ======================================== */
#svgPaths {
    position: absolute;
    /* Reaches up behind the hero window: the lines are born out of sight
       under it and emerge from its lower edge. */
    top: -485px;
    z-index: 1;
    width: 740px;
    max-width: 100%;
    overflow-x: clip;
    height: 5760px;
    filter: blur(1px);
    pointer-events: none;
}

@media (min-width: 576px) {
    #svgPaths {
        -webkit-transform: translateX(6vw);
        transform: translateX(6vw);
    }
}

#svgPaths use {
    fill: none;
    stroke: url(#lineFade);
    stroke-linecap: round;
}

#svgPaths use[href="#linePath01"] {
    --dot: 20px; --gap: 50px;
    stroke-dasharray: var(--dot) var(--gap) 120px var(--gap) var(--dot) var(--gap) 300px var(--gap) var(--dot) var(--gap) 150px var(--gap) var(--dot) 20000px;
}

#svgPaths use[href="#linePath02"] {
    --dot: 34px; --gap: 60px;
    stroke-dasharray: var(--dot) var(--gap) 120px var(--gap) var(--dot) var(--gap) 300px var(--gap) var(--dot) var(--gap) 150px var(--gap) var(--dot) 20000px;
}

#svgPaths use[href="#linePath03"] {
    --dot: 25px; --gap: 40px;
    stroke-dasharray: var(--dot) var(--gap) 120px var(--gap) var(--dot) var(--gap) 250px var(--gap) var(--dot) var(--gap) 150px var(--gap) var(--dot) 20000px;
}

#svgPaths use[href="#linePath04"] {
    --dot: 40px; --gap: 70px;
    stroke-dasharray: var(--dot) var(--gap) 100px var(--gap) var(--dot) var(--gap) 200px var(--gap) var(--dot) 20000px;
}

/* ========================================
   Infinity Finale
   ======================================== */
/* Its own surface, sized to the finale only. The blur here costs 740x800px
   per frame instead of the 740x5200px of #svgPaths. */
#svgFinale {
    position: absolute;
    top: 4525px;
    z-index: 1;
    width: 740px;
    max-width: 100%;
    height: 800px;
    filter: blur(1px);
    pointer-events: none;
}

@media (min-width: 576px) {
    #svgFinale {
        -webkit-transform: translateX(6vw);
        transform: translateX(6vw);
    }
}
#infinityGroup path {
    fill: none;
    stroke: #ff8c42;
    stroke-linecap: round;
}

/* Same weight and colour as the scrolling lines, so the symbol reads as
   those lines closing on themselves rather than a separate graphic. */
.inf-loop {
    stroke-width: 1.2;
    opacity: 0;
}

.inf-runner {
    stroke-width: 2.6;
    stroke: #ffc9a0;
    opacity: 0;
}

/* Flowing wave texture behind the symbol (built in script.js) */
#infinityTexture path {
    fill: none;
    stroke: #ff8c42;
    stroke-width: 1;
}

/* ========================================
   Film Grain
   ======================================== */
.grain {
    position: fixed;
    inset: -150%;
    width: 400%;
    height: 400%;
    z-index: 50;
    pointer-events: none;
    opacity: 0.035;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    animation: grainShift 0.6s steps(1) infinite;
}

@keyframes grainShift {
    0%   { transform: translate(0, 0); }
    20%  { transform: translate(-3%, -2%); }
    40%  { transform: translate(2%, 4%); }
    60%  { transform: translate(-4%, 1%); }
    80%  { transform: translate(3%, -3%); }
    100% { transform: translate(-1%, 2%); }
}

@media (prefers-reduced-motion: reduce) {
    .grain {
        animation: none;
    }
}
