/* ========================================================= */
/*                       PRODITAE v1.0                        */
/* ========================================================= */

/* -------------------------------------------------------------
   RENAMED / RELOCATED — read this first if you're confused
   about which CSS file is "the real one":

   This file used to live at assets/bootstrap/css/bootstrap.min.css
   and was named as if it were the Bootstrap framework's own
   stylesheet. It never was — it has always been 100% this
   site's own custom CSS (zero real Bootstrap framework rules
   in here; no .container, .row, .btn, --bs- variables, etc.).
   The old name and location were just leftover from how
   Bootstrap Studio's project export originally labeled it, and
   it caused confusion when trying to re-import the project
   elsewhere. It's been moved here, to assets/css/styles.css,
   and renamed to make that distinction obvious.

   The ACTUAL Bootstrap framework files (the real v5.3.8
   library) are separate, at assets/vendor/bootstrap/ — those
   ARE genuine, untouched Bootstrap files, safe to treat as a
   normal third-party library you never need to hand-edit.

   Nothing in the CSS below changed — only the file's name and
   folder.
------------------------------------------------------------- */

/* -------------------------------------------------------------
   HOW THIS FILE IS ORGANIZED — read this first

   This stylesheet was built inside Bootstrap Studio's visual
   editor, then hand-edited a lot on top of that. The single
   biggest thing to understand about it:

   MANY SELECTORS APPEAR MORE THAN ONCE IN THIS FILE.
   You'll find several separate ".photo{ ... }" blocks,
   several ".logo img{ ... }" blocks, two ".gradient{ ... }"
   blocks, and so on, scattered at different points in the
   file rather than grouped together. This isn't a mistake —
   it's just how Bootstrap Studio's visual style panels work:
   every time a property was changed through the app's UI, it
   tended to add a NEW rule block instead of editing the
   existing one for that selector.

   This matters because of how CSS actually resolves this:
   when the same selector (with the same specificity) appears
   more than once, the browser doesn't pick one block and
   ignore the rest — it merges them, property by property.
   For any single property, whichever block sets it LAST
   (furthest down the file) is the one that actually applies.
   Blocks earlier in the file still matter for any property
   they set that ISN'T overridden later.

   Practical takeaways:
   - If you're hunting for why an element looks a certain way,
     search (Ctrl+F) for its selector — you'll likely find it
     in more than one place, and the true final look is a mix
     of all of them.
   - If you change a property and nothing seems to happen,
     there's a good chance a LATER block in the file is setting
     that same property and winning. Search for more copies of
     the selector further down.
   - The most reliable way to see the real, final result for
     any element is your browser's DevTools: right-click the
     element → Inspect → the Styles panel lists every rule
     touching it, with anything being overridden shown with a
     strikethrough. That beats guessing from the file alone.
   - We hit two real bugs from this exact pattern while
     building this site: an earlier ".logo img" block's width
     getting silently overridden by a later one, and a brand
     new animation accidentally being given the same name as
     an existing one further down the file (search this file
     for "gatePowerOnFlicker" to read the full story where it
     happened). Worth keeping in mind before adding anything
     new — a quick search for a name before reusing it saves a
     lot of confusion later.

   This file is organized into clearly-labeled sections below
   (RESET, VARIABLES, BACKGROUND, DOORS, and so on). Within a
   section you'll mostly find rules for that area, but thanks
   to the above, don't be surprised to find another small
   addition to e.g. ".photo" showing up much later in the file
   too, sometimes with no section header nearby at all — those
   later, "orphan" blocks are usually small tweaks that were
   added on top of an already-working section.
------------------------------------------------------------- */

/* --------------------------------------------------------- */
/* FONTS                                                      */
/* --------------------------------------------------------- */
/* Caveat (the handwritten accent font used on the blinkies and
   the "now playing" line) is self-hosted — the actual font
   files live in assets/fonts/, so this works completely
   offline, no internet connection or Google Fonts CDN needed.

   This is a VARIABLE font: one file (Caveat-Variable) that can
   render any weight from 400 to 700, rather than needing a
   separate file per weight. font-weight:400 700 below is what
   tells the browser this file covers that whole range — CSS
   elsewhere in this file asking for weight 500 or 700 (see
   ".blinkie" and ".nowPlaying") will get exactly that weight
   rendered from this one file.

   .woff2 is listed first (smaller, and every modern browser
   supports it) with the .ttf as a fallback for anything that
   somehow doesn't. Both files, plus the required OFL.txt
   license (Caveat is free/open-source under the SIL Open Font
   License — see that file for the full terms), live right next
   to each other in assets/fonts/.

   SAFE TO TWEAK: if you ever want a different accent font
   instead, download its files, drop them in assets/fonts/, and
   update the src: paths below plus the font-family name — then
   update the two "font-family:'Caveat'" references further down
   this file to match.
--------------------------------------------------------- */
@font-face{

    font-family:'Caveat';

    src:

        url("assets/fonts/Caveat-Variable.woff2") format("woff2-variations"),

        url("assets/fonts/Caveat-Variable.ttf") format("truetype-variations");

    font-weight:400 700;

    font-style:normal;

    font-display:swap;

}

/* --------------------------------------------------------- */
/* RESET                                                     */
/* --------------------------------------------------------- */
/* Every browser ships its own default spacing/sizing for
   elements (headings, lists, buttons, etc.), and they don't
   all agree with each other. This block wipes that slate
   clean — zero margin, zero padding, and box-sizing:border-box
   (which makes any border/padding you add count INSIDE an
   element's declared width/height, instead of adding to it —
   much more predictable to work with). Nearly every modern
   site starts with something like this. Safe to leave alone;
   if things look "too cramped" somewhere, it's almost always
   easier to add margin/padding back on that specific element
   than to change this global reset. */

*,
*::before,
*::after{

    margin:0;
    padding:0;

    box-sizing:border-box;

}

/* --------------------------------------------------------- */
/* VARIABLES                                                  */
/* --------------------------------------------------------- */
/* These are CSS custom properties (a.k.a. CSS variables) —
   reusable values you can reference anywhere else in this file
   with var(--name), instead of retyping the same color/shadow
   over and over. Not every color in this file actually uses
   these (a lot of colors below are just written directly as
   rgba(...) instead), but where you DO see var(--pink) etc.,
   changing the value here updates every place that uses it at
   once. SAFE TO TWEAK: any of the hex/rgba values below — this
   is genuinely one of the lowest-risk places in the whole file
   to experiment with the color palette. */

:root{

    --black:#050505;

    --black2:#101010;

    --gray:#444;

    --white:#ECECEC;

    --pink:#ff87c9;

    --pink2:#ff5fa8;

    --pink3:#a62c67;

    --glass:rgba(255,255,255,.05);

    --border:rgba(255,255,255,.15);

    --shadow:

        0 0 25px rgba(255,110,190,.12);

}

/* --------------------------------------------------------- */
/* HTML                                                       */
/* --------------------------------------------------------- */
/* scroll-behavior:smooth just means any programmatic or
   anchor-link scrolling on the page eases in/out smoothly
   instead of jumping instantly. Doesn't affect normal mouse-
   wheel scrolling. */

html{

    scroll-behavior:smooth;

}

/* --------------------------------------------------------- */
/* BODY                                                       */
/* --------------------------------------------------------- */
/* overflow-x:hidden / overflow-y:auto: this pair had a real
   bug history — see the long note at the top of this file
   about duplicate selectors. In short: body used to be
   overflow:hidden entirely (no scrolling at all, by design —
   this page was meant to be a single, fixed "screen"), but
   that meant that on short windows, content that didn't fit
   got permanently cut off with no way to reach it. This
   version keeps horizontal scrolling blocked (you never want
   a sideways scrollbar here) but allows vertical scrolling as
   a safety net — invisible on any normal-height screen, but
   there if content ever needs it. Don't change overflow-y back
   to hidden unless you're confident everything always fits
   every screen size, or that clipping risk comes right back. */

body{

    background:var(--black);

    color:var(--white);

    font-family:Tahoma,Verdana,sans-serif;

    overflow-x:hidden;

    overflow-y:auto;

    min-height:100vh;

}
/* ========================================================= */
/* BACKGROUND                                                 */
/* ========================================================= */
/* Everything in this section stacks on top of itself, in the
   order these divs appear in the HTML, to build up the whole
   moody backdrop. All of it is position:fixed/absolute and
   pointer-events isn't blocked, so none of this ever gets in
   the way of clicking things, and none of it moves when the
   page scrolls — it's glued to the screen, not the page.

   .background — the outer fixed, full-screen container for
   every layer below. z-index:-100 keeps the whole stack
   permanently behind every real piece of content on the page.
   overflow:hidden here is what keeps oversized layers (like
   .noise below) from spilling out and being visible/scrollable
   — DON'T remove or override this overflow:hidden lightly; we
   ran into a real bug earlier where an accidental inline
   override of exactly this property caused a second, broken
   scrollbar to appear.

   .backgroundImage — your uploaded photo, stretched to always
   fully cover the screen (background-size:cover) and centered.
   SAFE TO TWEAK: swap the url() to point at a different image
   any time; background-position can be changed to e.g. "top
   center" or "bottom center" if cover-cropping is cutting off
   a part of the image you want visible.

   .gradient — the dark, moody tint sitting over your photo.
   It's built from three layers combined into one background:
   a soft pink glow at the top, a dimmer purple-pink glow at
   the bottom, and a dark semi-transparent base underneath both
   (this base used to be fully OPAQUE, which completely hid the
   background photo — it was made semi-transparent specifically
   so the photo shows through). SAFE TO TWEAK: raise/lower the
   alpha (the last number in each rgba(...)) to make the whole
   scene lighter or darker/moodier.

   .vignette — darkens the very edges of the screen using inset
   box-shadows (a shadow that projects INWARD instead of
   outward), which is what gives the "looking through a lens/
   old screen" framing effect. SAFE TO TWEAK: the two blur radii
   (250px/150px) control how far the darkening reaches in from
   the edge.

   .scanlines — a very faint repeating horizontal stripe
   pattern, like an old CRT's visible scan lines. Barely
   visible on purpose (opacity:.08).

   .noise — a faint animated static/grain texture. Notice
   inset:-100% instead of inset:0 like everything else here:
   that deliberately makes this layer 3× the width and 3× the
   height of the screen (each edge pushed out by 100% of the
   container's own size), centered on screen. That's on purpose
   — it gives the pan animation (noiseMove, a few lines below)
   room to shift the texture around without ever revealing a
   hard edge. Because .background above has overflow:hidden,
   none of that extra size is ever actually visible or
   scrollable — it's just working space for the animation.

   .particles — an empty container. It stays empty in the HTML;
   script.js's createParticles() function fills it with the
   small floating pink dots at runtime, in JavaScript, not here.
------------------------------------------------------------- */

.background{

    position:fixed;

    inset:0;

    overflow:hidden;

    z-index:-100;

}
.backgroundImage{

    position:absolute;

    inset:0;

    background-image:url("assets/img/Background_Web_Proditae.png");

    background-size:cover;

    background-position:center;

}
/* ---------------------------------------------------------
   BACKGROUND VIDEO (optional — off by default)
   A video version of .backgroundImage above. The <video>
   element itself lives in index.html, inside <div
   class="background">, right after <div class="backgroundImage">
   — but it's wrapped in an HTML comment there, so it does
   nothing until you remove those comment markers. This CSS
   rule is harmless either way, since it only applies to an
   element that isn't actually on the page yet.

   WHY IT IS SAFE TO TURN ON, IN PLAIN TERMS:

   - It sits in the exact same spot in the stacking order as
     .backgroundImage (same parent, right after it in the HTML),
     so it inherits everything .background already does for you:
     position:fixed, z-index:-100, overflow:hidden. In other
     words, it's exactly as "safely behind everything and never
     blocks clicks" as your photo background already is — this
     is not a new stacking layer to worry about.
   - It never depends on the internet: no CDN, no streaming
     service, nothing but a video file that lives in
     assets/video/, right next to your other local assets.
   - It's a normal HTML5 <video> tag with FOUR attributes doing
     specific jobs — safe to know what each one does before you
     remove any of them:
       autoplay  → starts playing on its own, no click needed
       muted     → REQUIRED for autoplay to work in every modern
                   browser. Browsers block autoplay with sound
                   as a spam-prevention rule; a silent decorative
                   background video is exactly the case autoplay
                   is still allowed for. If you remove "muted",
                   the video will very likely just sit frozen on
                   its first frame instead of playing.
       loop      → restarts from the beginning when it ends, so
                   it behaves like a seamless looping background
                   instead of stopping and freezing on its last
                   frame.
       playsinline → stops iPhones from hijacking the video into
                   a fullscreen player the moment it starts —
                   without this, iOS Safari can take over the
                   whole screen instead of playing quietly in
                   the background.
   - poster="assets/img/Background_Web_Proditae.png" — the SAME
     image file .backgroundImage already uses. This shows
     immediately while the video file is still loading, and
     keeps showing instead of a blank box if the video ever
     fails to load at all (wrong filename, unsupported format,
     browser blocks it, etc.) — so worst case, it just quietly
     behaves like your current photo background, never a broken
     empty rectangle.

   FILE FORMAT / WHERE TO PUT YOUR VIDEO:

   Create a folder assets/video/ (a placeholder file is already
   there for you) and drop your video in as BOTH of these two
   filenames if you can manage it:
       assets/video/background.webm
       assets/video/background.mp4
   The <video> tag lists webm first and mp4 second on purpose —
   browsers check <source> tags top to bottom and use the FIRST
   one whose format they understand, so listing the smaller/
   better-compressed format (webm, usually 30-50% smaller than
   mp4 at similar quality) first means browsers that support it
   use it, while older/other browsers fall through to the mp4
   automatically. You don't have to provide both — one <source>
   with just the mp4 works completely fine on its own too; just
   delete the webm <source> line if you only have an mp4.

   Unlike Wix (or most hosted site builders), there's no
   platform-imposed file size ceiling here at all — this is
   just a local file sitting in a folder, so its only real
   limits are your pendrive's storage space and, once this site
   is ever actually visited by someone over the internet rather
   than opened locally, ordinary web-loading-speed sense (a
   30-second, well-compressed 1080p clip is usually well under
   10MB; a raw, uncompressed 4K file could be gigabytes — most
   video editors have an "export for web" preset that handles
   this compression for you).

   SAFE TO TWEAK:
   - Swap either source's filename to point at a different clip.
   - Delete the "loop" attribute if you'd rather it play once
     and freeze on its last frame.
   - object-position below can be changed to e.g. "top center"
     the same way .backgroundImage's background-position can, if
     cover-cropping hides a part of the video you want visible.
--------------------------------------------------------- */
.backgroundVideo{

    position:absolute;

    inset:0;

    width:100%;

    height:100%;

    object-fit:cover;

    object-position:center;

}
/* respects the visitor's OS-level "reduce motion" accessibility
   setting by hiding the video outright, which quietly reveals
   the plain, static .backgroundImage sitting right behind it —
   no JavaScript needed for this fallback, it's automatic. */
@media (prefers-reduced-motion:reduce){

    .backgroundVideo{

        display:none;

    }

}
.gradient{

    position:absolute;

    inset:0;

    background:

        radial-gradient(circle at top,

        rgba(255,70,150,.18),

        transparent 45%),

        radial-gradient(circle at bottom,

        rgba(140,40,90,.15),

        transparent 55%),

        linear-gradient(

            rgba(17,17,17,.65),

            rgba(5,5,5,.85)

        );

}.vignette{

    position:absolute;

    inset:0;

    pointer-events:none;

    box-shadow:

        inset 0 0 250px black,

        inset 0 0 150px black;

}
.scanlines{

    position:absolute;

    inset:0;

    opacity:.08;

    background:

        repeating-linear-gradient(

            to bottom,

            transparent 0px,

            transparent 2px,

            rgba(255,255,255,.04) 3px,

            transparent 4px

        );

}
/* the pan animation .noise uses — see the .noise note above
   for why the element is oversized to begin with */
.noise{

    position:absolute;

    inset:-100%;

    opacity:.05;

    background-image:url("assets/textures/noise.png");

    animation:

        noiseMove 0.35s infinite;

}
.particles{

    position:absolute;

    inset:0;

    pointer-events:none;

}
@keyframes noiseMove{

0%{

transform:translate(0,0);

}

25%{

transform:translate(-2%,1%);

}

50%{

transform:translate(2%,0);

}

75%{

transform:translate(1%,-2%);

}

100%{

transform:translate(0,0);

}

}
/* ========================================================= */
/* MAIN                                                       */
/* ========================================================= */
/* .portal is the big flex container holding the logo, quote,
   the two archive cards, ticker, and footer — everything the
   visitor actually reads/clicks. min-height:100vh + the flex
   centering is what keeps it filling and centering in the
   screen. It used to be a fixed height:100vh, which forced
   content taller than the window to get cropped in half off
   the top AND bottom — min-height lets it grow instead when
   content needs more room, and the padding below guarantees
   breathing room above/below even on short screens. */

.portal{

    width:100%;

    min-height:100vh;

    display:flex;

    flex-direction:column;

    justify-content:center;

    align-items:center;

    padding:30px 0;

}
.logo{

    text-align:center;

    margin-bottom:20px;

}

.logo img{

    /* NOTE: ".logo img" appears three times total in this file
       (search to find the others). This first one sets the
       actual SIZE (width/max-width/height) — that part sticks.
       Its animation/filter get fully replaced by a later block
       though, per the cascade-order note at the top of this
       file. */

    width:320px;

    max-width:60vw;

    height:auto;

    cursor:pointer;

    animation:

        breathe 7s ease-in-out infinite;

    filter:

        drop-shadow(0 0 10px rgba(255,100,180,.25));

}

/* ---------------------------------------------------------
   CONTACT / SUPPORT BUTTON ROW
   The row of six pill-shaped buttons under the skull logo and
   above the "Ruido Fantasma" now-playing line (Email, Telegram,
   WhatsApp, Twitter, Cafecito, Patreon). Markup lives in
   index.html inside <header class="logo">, right after the
   <img>.

   HOW THIS IS BUILT, so you can edit it without help:

   - .contactRow is just a flexbox row (display:flex +
     flex-wrap:wrap). On a narrow phone screen, six buttons
     with text labels won't all fit on one line — flex-wrap
     lets them drop to a second (or third) row automatically
     instead of overflowing or shrinking unreadably. This is
     why "legible on phones" doesn't need a separate mobile
     stylesheet or a media query here: wrapping handles it.

   - Every button is one <a class="contactBtn">, containing one
     inline <svg class="contactIcon"> and one <span> with the
     visible label. Icons are hand-drawn inline SVG paths (not
     an icon font/library), so nothing here ever needs internet
     access to display correctly — that was a specific
     requirement, same as the self-hosted Caveat font below.

   - Two buttons (Cafecito, Patreon) also carry a second class,
     "contactBtn--support", which gives them a filled pink
     background instead of just an outline — a small visual cue
     that those two are "support me" links rather than "contact
     me" links. If you add another donation-type link later,
     just add class="contactBtn contactBtn--support" to it too.

   - Font: the labels use the same system-font stack as most
     modern apps/phones use for their own interface text
     (Segoe UI on Windows, San Francisco on iOS/Mac, Roboto on
     Android) — NOT a downloaded font file. This was a
     deliberate choice: it looks noticeably cleaner and more
     "designed" than the site's base Tahoma/Verdana, reads
     very clearly at small button sizes on a phone, and — like
     every font already used elsewhere on this page — never
     makes a network request, since the browser is just asking
     each device to use a font it already has installed.

   TO ADD A 7TH BUTTON: copy one whole <a class="contactBtn">
   block in index.html (with or without --support), give it a
   new href, swap the <svg> for a different icon path, and
   change the label text. No CSS changes needed — .contactBtn
   styling applies automatically to any element with that class.

   TO REMOVE A BUTTON: just delete its whole <a>...</a> block
   from index.html. The row re-centers itself automatically.

   TO RESTYLE (colors/size/spacing): everything below uses the
   same --pink / --pink2 / --pink3 / --glass / --border
   variables defined in :root up top, so tweaking those
   variables will also retint this row along with the rest of
   the page. Padding, gap, border-radius, and font-size below
   are the only page-specific numbers if you want to make the
   buttons bigger/smaller/rounder without touching :root.
--------------------------------------------------------- */
.contactRow{

    display:flex;

    flex-wrap:wrap;

    justify-content:center;

    align-items:center;

    gap:10px;

    margin-top:18px;

}

.contactBtn{

    display:inline-flex;

    align-items:center;

    gap:6px;

    padding:8px 16px;

    border-radius:999px;

    border:1px solid rgba(255,135,201,.4);

    background:var(--glass);

    color:var(--white);

    text-decoration:none;

    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;

    font-size:12px;

    font-weight:600;

    letter-spacing:.4px;

    line-height:1;

    white-space:nowrap;

    transition:all .25s ease;

}

.contactBtn:hover,
.contactBtn:focus-visible{

    background:rgba(255,135,201,.14);

    border-color:var(--pink);

    color:var(--pink);

    box-shadow:var(--shadow);

    transform:translateY(-1px);

}

.contactIcon{

    width:14px;

    height:14px;

    flex-shrink:0;

}

/* the two "support me" links (Cafecito, Patreon) get a solid
   pink-to-plum gradient fill instead of the plain outline, so
   they read as a slightly different "type" of button at a
   glance — donation links, not just contact links. */
.contactBtn--support{

    background:linear-gradient(135deg,var(--pink2),var(--pink3));

    border-color:transparent;

    color:#fff;

}

.contactBtn--support:hover,
.contactBtn--support:focus-visible{

    background:linear-gradient(135deg,var(--pink),var(--pink2));

    border-color:transparent;

    color:#fff;

    box-shadow:0 0 25px rgba(255,110,190,.35);

    transform:translateY(-1px);

}

/* on very narrow phones, drop the side padding a touch so six
   pill buttons don't force a 3rd wrapped row unnecessarily */
@media (max-width:420px){

    .contactBtn{

        padding:7px 12px;

        font-size:11px;

    }

}

.subtitle{

    margin-top:20px;

    font-size:11px;

    letter-spacing:6px;

    color:#bcbcbc;

}
@keyframes breathe{

0%{

transform:scale(1);

}

50%{

transform:scale(1.02);

}

100%{

transform:scale(1);

}

}
/* ========================================================= */
/* DOORS                                                     */
/* ========================================================= */
/* "Doors" = the two clickable archive cards. .doors is just
   the flex row holding them side by side. */

.doors{

    width:1000px;

    max-width:95%;

    display:flex;

    justify-content:space-between;

    align-items:flex-start;

    margin-bottom:40px;

}
.archive{

    width:360px;

    display:flex;

    flex-direction:column;

    align-items:center;

    position:relative;

}
.archive:first-child{

    /* the slight opposite-direction rotation + vertical offset
       on each card is what gives the "scattered photos" look
       instead of two perfectly aligned boxes. transform never
       changes an element's actual layout space, only where it's
       PAINTED — so a big translateY here doesn't push anything
       else down to make room. That's exactly what caused a real
       clipping bug earlier (the offset card could get pushed
       below a short screen with no way to reach it) — now fixed
       by .portal's min-height + padding above being generous
       enough to always leave room for this offset. If you
       increase these translateY values much further, keep that
       in mind. */
    transform:

        rotate(-2deg)

        translateY(25px);

}

.archive:last-child{

    transform:

        rotate(2deg)

        translateY(90px);

}
.photo{

    /* the core photo card box. NOTE: ".photo" (bare, no hover/
       pseudo-class) appears NINE separate times across this
       file, each adding a few more properties on top of this
       one — border-radius, borders, animations, outlines, and
       so on all get layered on elsewhere. This first block sets
       the fundamentals: size, the dark background behind the
       (transparent-background) card images, and the base drop
       shadow. */
    width:320px;

    height:420px;

    overflow:hidden;

    position:relative;

    border:2px solid rgba(255,255,255,.15);

    background:#111;

    box-shadow:

        0 20px 45px rgba(0,0,0,.65),

        0 0 25px rgba(255,120,180,.10);

    transition:

        .45s ease;

}
.photo img{

    /* object-fit:cover makes the image fill the card's box
       without distorting, cropping the overflow instead —
       standard technique for "fill this box no matter the
       image's real aspect ratio." The dimmed/desaturated
       filter is the moody, muted look; it brightens back up on
       hover (see ".archive:hover img" further down). */
    width:100%;

    height:100%;

    object-fit:cover;

    filter:

        brightness(.75)

        saturate(.65)

        contrast(1.05);

    transition:.55s;

}
.photo::after{

    /* darkens toward the bottom of each photo, purely for
       depth/readability. */
    content:"";

    position:absolute;

    inset:0;

    background:

        linear-gradient(

            transparent,

            rgba(0,0,0,.45)

        );

    pointer-events:none;

}
.photo::before{

    /* this is the frosted "tape strip" across the top of each
       photo, like a real print taped to a page. NOTE: like
       ".photo", ".photo::before" gets added to more than once
       elsewhere in this file — its color/pattern for each card
       specifically was later overridden per-card with the pink/
       black diagonal-stripe washi-tape patterns (search
       "archive:first-child .photo::before" to find that). This
       block still supplies the actual SHAPE/position/blur of
       the tape; only its color got swapped later. */
    content:"";

    position:absolute;

    width:130px;

    height:28px;

    top:-12px;

    left:50%;

    transform:

        translateX(-50%)

        rotate(-3deg);

    background:

        rgba(255,255,255,.18);

    backdrop-filter:

        blur(3px);

    opacity:.55;

}
.label{

    /* the text block under each photo: "#001 / Archivo
       Proditae / Index". */
    width:100%;

    margin-top:22px;

    text-align:center;

}
.number{

    color:#ff9dcb;

    display:block;

    font-size:11px;

    letter-spacing:4px;

    margin-bottom:12px;

}
.label h2{

    font-family:Georgia,serif;

    font-weight:normal;

    font-size:32px;

    margin-bottom:10px;

}
.label p{

    color:#9a9a9a;

    line-height:1.8;

    font-size:13px;

    margin-bottom:24px;

}
/* --- .enter is DEAD / UNUSED CSS ---
   This styled the little "ENTER" text button that used to sit
   inside each card. It was removed a while back when the whole
   card itself became the clickable link instead — but the CSS
   for it was left in place rather than deleted (harmless either
   way, since nothing in the HTML has class="enter" anymore).
   There are several more ".enter" blocks scattered later in
   this file too, all equally unused. Safe to delete every
   ".enter" rule in this file if you want a cleaner stylesheet;
   equally safe to just leave them as unused leftovers. */
.enter{

    display:inline-block;

    padding:

        12px

        45px;

    color:white;

    text-decoration:none;

    border:

        1px solid

        rgba(255,255,255,.18);

    background:

        rgba(255,255,255,.04);

    letter-spacing:5px;

    font-size:11px;

    transition:.35s;

}
.enter:hover{

    background:

        rgba(255,110,180,.18);

    border-color:

        var(--pink);

    box-shadow:

        0 0 25px rgba(255,110,180,.25);

}
.archive:hover .photo{

    /* card lifts + scales up slightly on hover. NOTE: this
       exact selector, ".archive:hover .photo", appears twice
       in a row right here — that's not a mistake, they just
       each set a different property (transform vs box-shadow)
       and could safely be merged into one block if you wanted
       to tidy this up. */
    transform:

        translateY(-10px)

        scale(1.02);

}
.archive:hover img{

    /* the muted photo filter (see ".photo img" above) reverses
       back to normal brightness/color on hover. */
    filter:

        brightness(1)

        saturate(1)

        contrast(1.1);

}
.archive:hover .photo{

    box-shadow:

        0 30px 70px rgba(0,0,0,.7),

        0 0 35px rgba(255,120,180,.30);

}
.label h2::after{

    content:"";

    display:block;

    width:90px;

    height:1px;

    background:var(--pink);

    margin:

        18px auto;

}
/* the tape strip rotates slightly straighter on hover, like it's
   being pressed down. (This exact rule is duplicated twice in a
   row here — genuinely redundant, safe to delete one copy.) */
.archive:hover .photo::before{

    transform:

        translateX(-50%)

        rotate(2deg);

}
.archive:hover .photo::before{

    transform:

        translateX(-50%)

        rotate(2deg);

}
/* a faint, slowly-drifting dust texture layered over the whole
   background stack — separate from .noise (the flickery static)
   further up; this one moves in one steady direction instead of
   jittering. */
.background::after{

    content:"";

    position:absolute;

    inset:0;

    background-image:

        url("assets/textures/dust.png");

    background-size:cover;

    opacity:.10;

    animation:

        dust 45s linear infinite;

}
@keyframes dust{

0%{

transform:translateY(0);

}

100%{

transform:translateY(-80px);

}

}
/* two more ambient layers, this time directly on <body> rather
   than inside the .background stack — functionally similar,
   just added at a different point in the project. mix-blend-
   mode controls how a layer's colors combine with what's behind
   it ("multiply" darkens, like stacking semi-transparent film).
   body::after is a big soft pink glow centered on the page; it
   gets a slow rotation animation added to it later in this file
   (search "screenGlow" to find it) — barely noticeable since the
   glow is a symmetric circle, but technically always turning. */
body::before{

    content:"";

    position:fixed;

    inset:0;

    pointer-events:none;

    background:

        radial-gradient(

            circle,

            transparent 60%,

            rgba(0,0,0,.08)

        );

    mix-blend-mode:multiply;

}
body::after{

    content:"";

    position:fixed;

    width:900px;

    height:900px;

    left:50%;

    top:50%;

    transform:

        translate(-50%,-50%);

    background:

        radial-gradient(

            circle,

            rgba(255,90,170,.08),

            transparent 70%

        );

    pointer-events:none;

}
.photo{

    border-radius:4px;

}

.photo::after{

    /* a second, subtler tint layer on top of the first
       .photo::after — mix-blend-mode:overlay boosts contrast
       (lightens light areas, darkens dark ones) rather than
       flatly darkening like the first one did. */
    content:"";

    position:absolute;

    inset:0;

    background:

        linear-gradient(

            rgba(255,255,255,.03),

            rgba(0,0,0,.18)

        );

    mix-blend-mode:overlay;

}
.photo img{

    /* another dimming pass on the photo — this is the block
       that actually wins (see the cascade-order note at the
       top of this file), since it comes after the first
       ".photo img" filter set earlier. */
    image-rendering:auto;

    filter:

        brightness(.72)

        contrast(1.06)

        saturate(.70);

}
.photo{

    /* clip-path cuts the card into a custom shape instead of a
       plain rectangle — here, a barely-there diagonal snip on
       the bottom-right corner (the "98% 100%" point), like a
       corner has been sliced off. This pairs with the separate
       .foldCorner element (added later, see the SCENE-QUEEN
       section near the end of this file) which draws a little
       paper-fold triangle sitting right on top of this same
       corner — together they read as a lifted photo corner. */
    clip-path:

        polygon(

        0 0,

        100% 0,

        100% 99%,

        98% 100%,

        0 100%

        );

}
/* the "ONLINE" sticker, top-right. Absolutely positioned
   relative to .portal (its nearest positioned ancestor), tilted
   with rotate(14deg) for the hand-stuck-on-crooked look. Hover/
   click sound + the little press-down bounce animation are
   wired up separately in script.js (setupStickerSFX) and just
   below this block (.sticker.bounce / @keyframes stickerBounce). */
.sticker{

    position:absolute;

    top:18px;

    right:-12px;

    padding:

        6px

        14px;

    background:

        #ff6db4;

    color:black;

    font-size:10px;

    font-weight:bold;

    letter-spacing:2px;

    cursor:pointer;

    transform:

        rotate(14deg);

    box-shadow:

        0 0 15px rgba(255,110,180,.35);

}
.sticker.bounce{

    animation: stickerBounce .45s ease;

}
@keyframes stickerBounce{

    0%{ transform: rotate(14deg) scale(1); }

    30%{ transform: rotate(8deg) scale(1.15); }

    55%{ transform: rotate(17deg) scale(.95); }

    100%{ transform: rotate(14deg) scale(1); }

}
.label{

    position:relative;

}
.label::before{

    /* IMPORTANT GOTCHA: the tiny "ARCHIVE" kicker text sitting
       just above each card's title isn't in the HTML at all —
       it's generated entirely by this rule's content:"ARCHIVE"
       property. If you ever want to change that word (e.g. to
       something else, or translate it), you have to edit it
       right here in the CSS, not in index.html — searching the
       HTML file for "ARCHIVE" won't find it. */
    content:"ARCHIVE";

    position:absolute;

    top:-20px;

    left:50%;

    transform:translateX(-50%);

    font-size:9px;

    letter-spacing:5px;

    color:#666;

}
/* more unused ".enter" leftovers (this set drew a diagonal
   shine sweeping across the old button on hover) — see the
   longer note the first time ".enter" shows up in this file. */
.enter{

    position:relative;

    overflow:hidden;

}
.enter::before{

    content:"";

    position:absolute;

    left:-150%;

    top:0;

    width:80%;

    height:100%;

    background:

        linear-gradient(

            transparent,

            rgba(255,255,255,.25),

            transparent

        );

    transform:skew(-25deg);

}
.enter:hover::before{

    left:170%;

    transition:1s;

}
/* FOOTER — the little "© PRODITAE" line + visitor counter at
   the very bottom. This used to be pinned to the bottom of the
   page on its own (position:absolute), independently of
   everything above it — which is exactly why it started
   overlapping the new scrolling ticker strip once that was
   added: two different positioning systems both trying to
   live in the same space. Now it's just a normal part of the
   stack (same as the logo, quote, and doors above it), so it
   always sits right after the ticker with no chance of
   overlapping, on any screen size. */
footer{

    margin-top:18px;

    text-align:center;

    color:#555;

    letter-spacing:4px;

    font-size:10px;

}
/* ::selection controls the highlight color when someone
   drag-selects text on the page (instead of the default blue).
   The three ::-webkit-scrollbar-* rules re-skin the vertical
   scrollbar to match the pink/black palette — heads up, that
   only works in Chromium/WebKit browsers (Chrome, Edge, Safari);
   Firefox uses a different, more limited scrollbar-color
   property instead and will just show its own default scrollbar
   here. Not a bug, just a browser limitation with no universal
   fix. */
::selection{

    background:#ff6eb8;

    color:black;

}
::-webkit-scrollbar{

    width:10px;

}

::-webkit-scrollbar-track{

    background:#111;

}

::-webkit-scrollbar-thumb{

    background:#ff78bd;

}
/* a custom cursor image for the whole page. The ", auto" at the
   end is a required fallback — if the .cur file fails to load
   for any reason, browsers fall back to the normal system arrow
   instead of breaking. SAFE TO TWEAK: swap the file for a
   different custom cursor any time (.cur, .png, .gif, and .svg
   are all supported) — just keep cursor images small (under
   ~128×128px is a safe bet); oversized cursor files get quietly
   ignored by some browsers and it'll silently fall back to
   "auto" instead. */
body{

    cursor:

        url("assets/cursors/cursor.cur"),

        auto;

}
.logo img{

    /* second of three ".logo img" blocks in this file (see the
       first one, up in the MAIN section, and the cascade-order
       note at the top of the file). THIS is the block that
       actually wins for animation and filter — the combined
       breathing + gentle floating motion, and the soft double
       pink glow. */
    width:320px;

    max-width:60vw;

    height:auto;

    position:relative;

    animation:

        breathe 8s ease-in-out infinite,

        logoFloat 10s ease-in-out infinite;

    filter:

        drop-shadow(0 0 12px rgba(255,120,190,.25))
        drop-shadow(0 0 30px rgba(255,70,170,.10));

}
.logo img.pulse{

    animation:

        breathe 8s ease-in-out infinite,

        logoFloat 10s ease-in-out infinite,

        logoPulse .5s ease-out;

}
@keyframes logoPulse{

    0%{
        filter:
            drop-shadow(0 0 12px rgba(255,120,190,.25))
            drop-shadow(0 0 30px rgba(255,70,170,.10));
        transform: scale(1);
    }

    40%{
        filter:
            drop-shadow(0 0 30px rgba(255,120,190,.7))
            drop-shadow(0 0 55px rgba(255,70,170,.35));
        transform: scale(1.045);
    }

    100%{
        filter:
            drop-shadow(0 0 12px rgba(255,120,190,.25))
            drop-shadow(0 0 30px rgba(255,70,170,.10));
        transform: scale(1);
    }

}
@keyframes logoFloat{

0%{

transform:translateY(0);

}

50%{

transform:translateY(-6px);

}

100%{

transform:translateY(0);

}

}
/* !! DO NOT rename this animation to reuse the name elsewhere !!
   This is a genuinely subtle, permanent flicker on the ENTIRE
   page — opacity dips by a fraction of a percent every 8
   seconds, barely visible on purpose. We hit a real, very
   visible bug once from giving a totally different, unrelated
   animation this exact same name elsewhere in the file: CSS
   silently lets the LAST @keyframes block with a given name win
   for every element using that name, so the new one completely
   replaced this subtle effect on <body> with a dramatic flash-
   to-black sequence, forever, on a loop. If you ever add a new
   animation, search this file for its name first. */
body{

    animation:

        crtFlicker 8s infinite;

}
@keyframes crtFlicker{

0%,96%,100%{

opacity:1;

}

97%{

opacity:.995;

}

98%{

opacity:.990;

}

99%{

opacity:.997;

}

}
/* a slow, breathing glow around each photo's shadow — box-shadow
   blur/opacity gently pulses over 7 seconds. */
.photo{

    animation:

        glowPulse 7s ease-in-out infinite;

}
@keyframes glowPulse{

0%{

box-shadow:

0 20px 45px rgba(0,0,0,.65),
0 0 15px rgba(255,120,180,.08);

}

50%{

box-shadow:

0 20px 45px rgba(0,0,0,.65),
0 0 30px rgba(255,120,180,.18);

}

100%{

box-shadow:

0 20px 45px rgba(0,0,0,.65),
0 0 15px rgba(255,120,180,.08);

}

}
/* second ".vignette" block — the first one (BACKGROUND section,
   near the top of this file) sets the actual box-shadow darkening;
   this one just adds a slow opacity breathing on top of it. */
.vignette{

    animation:

        vignetteBreath 12s ease-in-out infinite;

}
@keyframes vignetteBreath{

0%{

opacity:1;

}

50%{

opacity:.92;

}

100%{

opacity:1;

}

}
.label h2{

    text-shadow:

    0 0 10px rgba(255,130,190,.15);

}
.archive:hover h2{

    color:#ffd8ef;

}
.number{

    transition:.4s;

}
.archive:hover .number{

    letter-spacing:7px;

    color:white;

}
/* a very slow, continuous zoom breathing on the photo itself
   (scale 1 → 1.03 → 1), independent of the hover-triggered pop. */
.photo img{

    animation:

        imageBreath 12s ease-in-out infinite;

}
@keyframes imageBreath{

0%{

transform:scale(1);

}

50%{

transform:scale(1.03);

}

100%{

transform:scale(1);

}

}
.enter:hover{

    letter-spacing:8px;

}
/* second ".gradient" block — the first one (BACKGROUND section)
   sets the actual pink/purple/dark gradient colors; this just
   adds the slow 30-second scale breathing on top of it. */
.gradient{

    animation:

        gradientMove 30s linear infinite;

}
@keyframes gradientMove{

0%{

transform:scale(1);

}

50%{

transform:scale(1.08);

}

100%{

transform:scale(1);

}

}
.photo{

    outline:

    1px solid rgba(255,255,255,.05);

    outline-offset:6px;

}
.archive{

    filter:

        drop-shadow(0 30px 60px rgba(0,0,0,.45));

}
.photo img{

    image-rendering:auto;

}
/* .status is unused — no element with class="status" currently
   exists in index.html. Styled and ready to go if you ever want
   a small uppercase status line somewhere (an "est. 2008" note,
   a mood/status indicator, etc.) — just add an element with this
   class in the HTML and this styling will apply immediately. */
.status{

    margin-top:14px;

    color:#ff91ca;

    font-size:11px;

    letter-spacing:5px;

    text-transform:uppercase;

}
/* .ambient-light is unused (no ".ambient-light" element exists
   inside .background in the HTML) — and even if you added one,
   heads up that the "ambientPulse" animation these two identical
   blocks reference is never actually defined anywhere in this
   file, so it wouldn't animate even then; you'd need to add an
   @keyframes ambientPulse block yourself. Would've drawn a big,
   soft, slowly-pulsing pink glow circle behind everything. Also
   duplicated twice here for no reason — one copy can be deleted
   safely regardless. */
.background .ambient-light{

    position:absolute;

    width:1200px;

    height:1200px;

    left:50%;

    top:50%;

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

    border-radius:50%;

    background:

        radial-gradient(circle,

        rgba(255,110,180,.05),

        transparent 70%);

    animation:

        ambientPulse 18s ease-in-out infinite;

}
.logo img{

    image-rendering:auto;

    filter:

        drop-shadow(0 0 10px rgba(255,120,190,.35))

        contrast(1.04)

        saturate(1.08);

}
.logo{

    position:relative;

}
.logo::before{

    /* a faint, hue-shifted ghost watermark meant to sit behind
       the main skull logo. NOTE: it points at a DIFFERENT image
       file — assets/logos/logo.png — not the skull emblem
       actually used in index.html (assets/img/2CUT...webp). If
       that second file doesn't exist in your project, this
       silently renders nothing (a missing background-image just
       fails quietly, no visible error) — check whether you
       actually have a file at that path. If you don't want this
       ghosting effect at all, this whole block is safe to
       delete.

       pointer-events:none WAS MISSING HERE and is the reason the
       whole contact/support button row stopped being clickable.
       This pseudo-element is position:absolute + inset:0, so it
       fully covers the entire .logo header — invisibly, since
       it's only 8% opaque, but a browser's click hit-testing
       doesn't care about opacity, only about what's stacked on
       top. Any element with `position` set (like this one) is
       stacked above plain non-positioned siblings by default,
       REGARDLESS of which one comes first in the HTML — so this
       sat "in front of" the buttons even though it's written
       before them in the markup and is functionally invisible.
       This wasn't a bug when this rule was first written, since
       nothing inside .logo was clickable yet. Every other purely
       decorative overlay in this file (.cursorGlow, .crtGlass,
       .screenFlash, body::before/after, etc.) already has this
       same pointer-events:none for exactly this reason — it's
       what tells the browser "let clicks pass straight through
       me to whatever's underneath." */
    pointer-events:none;

    content:"";

    position:absolute;

    inset:0;

    background:url("assets/logos/logo.png");

    background-repeat:no-repeat;

    background-position:center;

    background-size:contain;

    opacity:.08;

    transform:

        translateX(2px);

    filter:hue-rotate(320deg);

}
.photo{

    /* deliberately UNEVEN corner radius (each corner a slightly
       different size) instead of a clean, uniform round-rect —
       a small detail that helps sell the "hand-cut, not
       machine-perfect" collage feeling. */
    border-radius:

    2px
    4px
    3px
    1px;

}
.archive:first-child .photo{

    /* each card's shadow is cast toward the OPPOSITE side from
       the other card's (-10px here vs +10px below) — makes it
       read like both photos share one consistent light source,
       rather than being lit identically and looking flat. */
    box-shadow:

        -10px 25px 55px rgba(0,0,0,.55),

        0 0 30px rgba(255,120,180,.18);

}
.archive:last-child .photo{

    box-shadow:

        10px 25px 55px rgba(0,0,0,.55),

        0 0 30px rgba(255,120,180,.18);

}
/* more unused ".enter" leftovers, same story as before. */
.enter{

    font-family:

        Tahoma,

        Verdana,

        sans-serif;

}
.enter:hover{

    transform:

        translateY(-3px);

}
.label p{

    color:#9d95a2;

}
/* adds the slow rotation to body::after (the big soft pink glow
   orb, defined earlier in this file) mentioned in that block's
   comment — rotating a symmetric circular gradient is subtle,
   but it's there. */
body::after{

    animation:

        screenGlow 25s linear infinite;

}
@keyframes screenGlow{

0%{

transform:

translate(-50%,-50%)

rotate(0deg);

}

100%{

transform:

translate(-50%,-50%)

rotate(360deg);

}

}
/* the italic quote line between the logo and the two cards —
   just plain text styling, edit the actual words in index.html. */
.quote{

    margin-top:25px;

    font-size:12px;

    font-style:italic;

    color:#7b7482;

    letter-spacing:1px;

}
/* .player is unused leftover CSS — looks like scaffolding from
   an earlier, never-finished attempt at a player widget, before
   the current cassette-style .mixtape player was built (see the
   MIXTAPE PLAYER section near the end of this file). WORTH
   KNOWING: it claims the exact same bottom:20px/right:20px
   corner that .mixtape now uses. It's inert as long as nothing
   in the HTML has class="player" (nothing currently does) — but
   if you ever reuse this class name for something else, it will
   visually collide with the cassette player. Safe to delete. */
.player{

    position:fixed;

    bottom:20px;

    right:20px;

    width:220px;

    height:60px;

    background:rgba(0,0,0,.45);

    border:1px solid rgba(255,255,255,.08);

    backdrop-filter:blur(10px);

}
.particle{

    position:absolute;

    width:3px;

    height:3px;

    border-radius:50%;

    background:#ff9dcb;

    filter:blur(1px);

    animation:

        floatParticle linear infinite;

}
@keyframes floatParticle{

0%{

transform:

translateY(0px);

}

50%{

transform:

translateY(-70px);

}

100%{

transform:

translateY(0px);

}

}
/* ---------------------------------------------------------
   CURSOR GLOW, SCREEN FLASH, GATE & MUTE TOGGLE
   These didn't exist in the original Bootstrap Studio project —
   added while building out the "Threshold" click-to-enter
   concept and the general interactivity.
--------------------------------------------------------- */

/* the soft pink light that follows the mouse around. Position
   is driven entirely by JS (script.js sets .style.left/.top on
   every mousemove) — this rule just defines its look. transform:
   translate(-50%,-50%) centers it exactly ON the cursor point
   rather than having the cursor at its corner. mix-blend-
   mode:screen makes it lighten whatever's underneath rather
   than sitting as a flat colored circle. */
.cursorGlow{

position:fixed;

width:300px;

height:300px;

border-radius:50%;

pointer-events:none;

background:

radial-gradient(circle,

rgba(255,120,190,.10),

transparent 70%);

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

mix-blend-mode:screen;

}
/* a full-screen white flash, briefly toggled to opacity:.85 and
   back by script.js right when you click into an archive card —
   gives the page-transition a little "camera flash" punch. */
.screenFlash{

    position:fixed;

    inset:0;

    background:white;

    opacity:0;

    pointer-events:none;

    z-index:99999;

    transition:opacity .12s;

}
/* the full-screen "click to enter" cover. See the long comment
   on the .gate element in index.html for the why (browsers
   block audio until a real click happens) — everything below
   here through .muteToggle:hover is just the visual styling for
   that gate screen and the top-left mute button. */
.gate{

    position:fixed;

    inset:0;

    z-index:100000;

    display:flex;

    align-items:center;

    justify-content:center;

    background:#050505;

    cursor:pointer;

    transition:opacity .8s ease, visibility .8s ease;

}
.gate.hidden{

    opacity:0;

    visibility:hidden;

    pointer-events:none;

}
.gateInner{

    text-align:center;

}
.gateHint{

    font-size:12px;

    letter-spacing:4px;

    text-transform:uppercase;

    color:#bcbcbc;

    margin-bottom:22px;

}
.gateEnter{

    font-family:inherit;

    background:transparent;

    border:1px solid rgba(255,120,190,.4);

    color:#fff;

    letter-spacing:6px;

    padding:14px 42px;

    font-size:13px;

    cursor:pointer;

    transition:all .3s ease;

}
.gateEnter:hover{

    background:rgba(255,120,190,.12);

    border-color:rgba(255,120,190,.8);

    box-shadow:0 0 20px rgba(255,100,180,.25);

}
.gateSound{

    margin-top:18px;

    font-size:11px;

    letter-spacing:2px;

    color:#666;

}
.muteToggle{

    position:fixed;

    top:22px;

    left:22px;

    z-index:100001;

    background:transparent;

    border:none;

    color:#bcbcbc;

    font-size:18px;

    cursor:pointer;

    opacity:.7;

    transition:opacity .2s ease;

}
.muteToggle:hover{

    opacity:1;

}
.archive:hover .photo{

    filter:

        brightness(1.05);

}
/* a nice one — plays ONCE (not looping) every time you hover a
   card: a quick brightness/contrast punch that mimics an old
   CRT monitor snapping on. Easy to miss just reading the
   property names, but worth knowing it's there. */
.archive:hover img{

    animation:

        monitorOn .45s ease;

}
@keyframes monitorOn{

0%{

filter:

brightness(.2)

contrast(2);

}

25%{

filter:

brightness(2);

}

55%{

filter:

brightness(.7);

}

100%{

filter:

brightness(1);

}

}
/* third ".photo::before" block — a diagonal light-streak/glare
   sweeping across the photo. Between this, the tape-strip block
   (up in the DOORS section), and the per-card washi-tape colors
   (in the SCENE-QUEEN RELICS section near the end of the file),
   there are three separate rules all shaping this one pseudo-
   element's final look — same cascade-merging principle as
   everywhere else in this file (see the top-of-file note). If
   you want to see exactly what's winning at a glance rather than
   working it out by reading the file, DevTools' Styles panel on
   a .photo element is the fastest way. */
.photo::before{

    content:"";

    position:absolute;

    inset:0;

    background:

    linear-gradient(

        120deg,

        transparent 0%,

        rgba(255,255,255,.10) 35%,

        transparent 60%

    );

    opacity:.25;

    pointer-events:none;

}
.photo{

    /* thick dark "frame" border around each photo, like a
       physical print mounted in a mat — heavier on the bottom
       edge (18px vs 10px) for a slight Polaroid-style look. */
    border:

        10px solid #111;

    border-bottom:

        18px solid #090909;

    background:black;

}
.photo{

    border-radius:

        8px;

}
.photo img{

    border-radius:

        5px;

}
.photo::after{

    content:"";

    position:absolute;

    inset:0;

    background:

        repeating-linear-gradient(

            to bottom,

            transparent 0px,

            transparent 2px,

            rgba(255,255,255,.03) 3px,

            transparent 4px

        );

}
.archive:hover{

    z-index:20;

}
.archive:hover{

    filter:

    drop-shadow(

    0 35px 70px

    rgba(0,0,0,.65));

}
.photo{

    animation:

        screenIdle 14s ease-in-out infinite;

}
@keyframes screenIdle{

0%{

transform:translateY(0);

}

50%{

transform:translateY(-3px);

}

100%{

transform:translateY(0);

}

}
.archive{

    cursor:pointer;

    text-decoration:none;

    color:inherit;

}

/* ========================================================= */
/* SCENE-QUEEN RELICS — CRT treatment, collage details,        */
/* and Y2K / Myspace-era touches                                */
/*                                                               */
/* Everything below this line was added for the nostalgia/CRT   */
/* aesthetic pass. It's grouped by feature, each with a plain-   */
/* English note on what it does and what's safe to play with.   */
/* None of this is required for the site to work — if anything  */
/* here ever looks wrong or you just don't like it, you can      */
/* delete that one block and nothing else will break.            */
/* ========================================================= */

/* ---------------------------------------------------------
   CRT GLASS REFLECTION
   A very faint diagonal streak of light in the upper-left,
   like light catching an old curved monitor's glass. Lives
   inside the .background layer stack, so it sits behind your
   logo/cards, not on top of them.
   SAFE TO TWEAK: the two ".05" and "18%" numbers control how
   bright/wide the streak is — raise .05 (e.g. to .10) for a
   more visible reflection, lower it to fade it out further.
--------------------------------------------------------- */
.crtGlass{

    position:absolute;

    inset:0;

    background:

        linear-gradient(115deg,
            rgba(255,255,255,.05) 0%,
            transparent 18%,
            transparent 100%);

    pointer-events:none;

}

/* ---------------------------------------------------------
   CRT SCAN ROLL
   A thin, barely-visible bright band that slowly drifts from
   the top of the screen to the bottom on an endless loop —
   the classic "old TV losing sync" look. Also lives inside
   the .background stack.
   SAFE TO TWEAK: change "11s" (below, in the animation line)
   to make it drift faster/slower. Raise ".035" for a more
   visible band, lower it to make it more subtle.
   NOTE: this animates `transform` on purpose instead of the
   more obvious `top` property — transform is far cheaper for
   the browser to animate forever, since it doesn't force a
   layout recalculation every frame. Worth keeping in mind for
   any other endless-loop animation you add later.
--------------------------------------------------------- */
.crtRoll{

    position:absolute;

    left:0;

    width:100%;

    height:120px;

    top:-120px;

    will-change:transform;

    background:

        linear-gradient(to bottom,
            transparent,
            rgba(255,255,255,.035),
            transparent);

    pointer-events:none;

    animation: crtRollMove 11s linear infinite;

}
@keyframes crtRollMove{

    0%{ transform:translateY(0); }

    100%{ transform:translateY(calc(100vh + 120px)); }

}

/* ---------------------------------------------------------
   CRT POWER-ON FLICKER
   A one-time white flash sequence that plays the instant
   someone clicks ENTER on the gate — like an old set warming
   up, instead of a plain fade. Triggered from script.js
   (search that file for "crtPowerOn" to see exactly where).
   The keyframes below are named "gatePowerOnFlicker" — please
   don't rename this to just "crtFlicker" again! There's an
   unrelated, much older and much subtler animation already
   using that exact name on the <body> element further up this
   file (search "crtFlicker" to find it) — reusing a name that
   already exists is exactly what caused the black-screen bug
   from before: whichever @keyframes block comes LAST in the
   file silently wins and overrides every other use of that
   name, anywhere in the stylesheet. When adding a new
   animation, it's always worth a quick search for its name
   first.
   SAFE TO TWEAK: the opacity numbers in @keyframes
   gatePowerOnFlicker control how many "flashes" happen and
   how strong each one is. The ".6s" in the animation line
   below is the total duration.
--------------------------------------------------------- */
.crtPowerOn{

    position:fixed;

    inset:0;

    background:white;

    opacity:0;

    pointer-events:none;

    z-index:99998;

}
.crtPowerOn.flicker{

    animation: gatePowerOnFlicker .6s steps(1,end);

}
@keyframes gatePowerOnFlicker{

    0%{ opacity:.9; }

    8%{ opacity:0; }

    15%{ opacity:.6; }

    22%{ opacity:0; }

    30%{ opacity:.35; }

    45%{ opacity:0; }

    100%{ opacity:0; }

}

/* ---------------------------------------------------------
   CHROMATIC ABERRATION ON HOVER
   A subtle red/cyan "ghosting" offset behind each card's
   title when you hover it — the retro screen-misalignment
   look. Pure text-shadow, no extra elements needed.
   SAFE TO TWEAK: the two rgba colors are the red and cyan
   ghosts. Lower their opacity (the last number, e.g. .5) to
   make the effect more subtle, or increase the -1px/1px
   offsets to make it more dramatic.
--------------------------------------------------------- */
.archive:hover h2{

    text-shadow:

        -1px 0 rgba(255,60,120,.5),
        1px 0 rgba(100,220,255,.35);

}

/* ---------------------------------------------------------
   WASHI TAPE — PER-CARD COLOR VARIATION
   Your photos already had a frosted "tape" strip across the
   top (that's the .photo::before rule further up this file —
   it was there before this session, we just gave it a
   pattern here instead of a plain white blur). These two
   rules give each of the two cards a different tape color/
   pattern so they don't look identical, like a real collage
   would have different bits of tape on different photos.
   SAFE TO TWEAK: swap the rgba colors for any two colors you
   like — the pattern is a diagonal stripe (repeating-linear-
   gradient), and the angle (45deg / -45deg) controls which
   way the stripes lean.
--------------------------------------------------------- */
.archive:first-child .photo::before{

    background:

        repeating-linear-gradient(45deg,
            rgba(255,140,190,.4) 0 6px,
            rgba(255,255,255,.18) 6px 12px);

}
.archive:last-child .photo::before{

    background:

        repeating-linear-gradient(-45deg,
            rgba(20,20,20,.5) 0 6px,
            rgba(255,255,255,.2) 6px 12px);

}

/* ---------------------------------------------------------
   FOLDED PHOTO CORNER
   A small triangle in the bottom-right of each photo, like a
   real photo corner lifting off the page. This is a "CSS
   triangle" — a 0×0-sized box where only two of its (invisible)
   borders are given a color, which is a common trick for
   drawing simple triangles/arrows without an image file.
   SAFE TO TWEAK: change "34px" (appears twice, in border-
   width) to make the fold bigger/smaller. The border-color's
   third value (rgba(255,255,255,.85)) is the fold's own
   color — the other three MUST stay "transparent" or the
   triangle trick breaks and you'll get a solid square instead.
--------------------------------------------------------- */
.foldCorner{

    position:absolute;

    right:0;

    bottom:0;

    width:0;

    height:0;

    border-style:solid;

    border-width:0 0 34px 34px;

    border-color:transparent transparent rgba(255,255,255,.85) transparent;

    box-shadow: -2px -2px 6px rgba(0,0,0,.35);

    pointer-events:none;

}

/* ---------------------------------------------------------
   PAPER-NOTE GLOW BEHIND EACH LABEL
   A very faint warm-toned glow sitting behind each card's
   caption text (the "#001 / Archivo Proditae / Index" block),
   like it's a little note pinned under the tape rather than
   floating on flat black. Deliberately subtle — this is meant
   to be felt more than seen.
   SAFE TO TWEAK: raise the ".05" for a more visible glow.
   The "inset:-10px -18px" controls how far the glow spreads
   beyond the text itself (top/bottom -10px, left/right -18px).
--------------------------------------------------------- */
.label{

    position:relative;

}
.label::before{

    content:"";

    position:absolute;

    inset:-10px -18px;

    background:

        radial-gradient(ellipse at center,
            rgba(255,235,225,.05),
            transparent 70%);

    z-index:-1;

    pointer-events:none;

}

/* ---------------------------------------------------------
   "NOW PLAYING" TICKER
   The small handwritten-style line under "PERSONAL DIGITAL
   ARCHIVE" referencing your ambient bed track by name.
   SAFE TO TWEAK: this is just styling — the actual text
   ("Ruido Fantasma") lives in index.html, inside the
   <header class="logo"> block. Change it there to whatever
   you actually end up calling your ambient track. Colors/
   size here are independent of that.
--------------------------------------------------------- */
.nowPlaying{

    margin-top:14px;

    font-family:'Caveat',cursive;

    font-size:19px;

    letter-spacing:1px;

    color:#ffb6d9;

    opacity:.85;

}

/* ---------------------------------------------------------
   SCROLLING TICKER STRIP
   The thin scrolling line of text between the two archive
   cards and the footer.
   SAFE TO TWEAK: the actual text lives in index.html (look
   for class="tickerTrack" — it's duplicated twice in a row on
   purpose, that's what makes the loop look seamless instead
   of visibly "jumping" when it restarts). "22s" below is how
   long one full scroll takes — lower it to scroll faster.
   "opacity:.55" on .tickerStrip controls how faint the whole
   strip is.
--------------------------------------------------------- */
.tickerStrip{

    width:100%;

    max-width:600px;

    overflow:hidden;

    margin-top:8px;

    opacity:.55;

}
.tickerTrack{

    display:flex;

    white-space:nowrap;

    width:max-content;

    font-size:11px;

    letter-spacing:3px;

    color:#bcbcbc;

    animation: tickerScroll 22s linear infinite;

}
.tickerTrack span{

    padding-right:40px;

}
@keyframes tickerScroll{

    0%{ transform:translateX(0); }

    100%{ transform:translateX(-50%); }

}

/* ---------------------------------------------------------
   BLINKIES
   The three small badges blinking in the bottom-left corner
   ("DESDE 2008" etc.) — a nod to the tiny animated badge
   buttons everyone had on their profile back in the day.
   Fixed to the corner, so they don't affect anything else's
   layout no matter how tall the page gets.
   SAFE TO TWEAK: the badge text lives in index.html (look for
   class="blinkie"). Colors are set per-badge just below
   (.blinkie1/.blinkie2/.blinkie3) — add a 4th by duplicating
   one of those lines with a new class name, and adding a
   matching <div class="blinkie blinkie4"> in the HTML.
   "88x31" (the width/height above) is the actual, real size
   real 2000s website buttons/blinkies used — a nice period-
   accurate detail if you keep it, but free to resize.
--------------------------------------------------------- */
.blinkies{

    position:fixed;

    bottom:20px;

    left:20px;

    z-index:50;

    display:flex;

    flex-direction:column;

    gap:4px;

}
.blinkie{

    width:88px;

    height:22px;

    display:flex;

    align-items:center;

    justify-content:center;

    text-align:center;

    font-family:'Caveat',cursive;

    font-weight:700;

    font-size:12px;

    letter-spacing:1px;

    color:#fff;

    border:1px solid rgba(255,255,255,.25);

    animation: blinkieFlash 1.6s steps(1,end) infinite;

}
.blinkie1{ background:#000; animation-delay:0s; }
.blinkie2{ background:#ff6db4; color:#000; animation-delay:.4s; }
.blinkie3{ background:#3a0d24; animation-delay:.8s; }
@keyframes blinkieFlash{

    0%,100%{ opacity:1; }

    50%{ opacity:.45; }

}

/* ---------------------------------------------------------
   VISITOR COUNTER
   Styling for the "visitantes: 000001" line in the footer.
   The actual counting logic (reading/saving the number) lives
   in script.js — search for "setupVisitorCounter" there.
   Heads up: this counts visits on THIS browser only (it's
   stored via localStorage, not a shared server count), so it
   won't match what a visitor on a different device/browser
   sees. It resets if someone clears their browser data.
   SAFE TO TWEAK: colors/font here are independent of the
   counting logic, change freely.
--------------------------------------------------------- */
.visitorCounter{

    margin-top:8px;

    font-family:'Courier New',monospace;

    font-size:11px;

    letter-spacing:3px;

    color:#777;

}
.visitorCounter span{

    color:#ff9dcb;

    background:#000;

    padding:2px 5px;

    border:1px solid rgba(255,157,203,.3);

}

/* ---------------------------------------------------------
   MIXTAPE PLAYER — the cassette in the bottom-right corner.
   Fixed to the corner like the blinkies, so it never affects
   the rest of the page's layout.

   Structure: .mixtape (the corner container) holds the
   .mixtapeBody button (the clickable cassette graphic itself
   — click it to play/pause) and .mixtapeControls (the small
   prev/next buttons underneath). The actual playback logic
   lives in script.js, under "MIXTAPE PLAYER".

   The two .reel groups inside the SVG spin continuously via
   the reelSpin animation below, but sit paused
   (animation-play-state:paused) until script.js adds the
   "playing" class to .mixtape — that's what the
   .mixtape.playing rule targets.
--------------------------------------------------------- */
.mixtape{

    position:fixed;

    bottom:20px;

    right:20px;

    z-index:50;

    display:flex;

    flex-direction:column;

    align-items:center;

    gap:6px;

}
.mixtapeBody{

    position:relative; /* lets .mixtapeLabel below position itself
                           relative to this button, on top of the SVG */

    background:none;

    border:none;

    padding:0;

    line-height:0; /* prevents the browser adding invisible extra
                       space below the SVG, since inline SVGs are
                       treated like inline text by default */

    cursor:pointer;

}
.cassetteSvg{

    width:92px;

    height:auto;

    filter: drop-shadow(0 0 8px rgba(255,109,180,.15));

    transition: filter .3s ease;

}
.mixtapeBody:hover .cassetteSvg{

    /* SAFE TO TWEAK: raise this glow on hover for a stronger
       "this is interactive" cue */
    filter: drop-shadow(0 0 14px rgba(255,109,180,.35));

}
/* the "MIXTAPE" label — plain HTML text, positioned to sit exactly
   over the paper-label rect drawn inside the SVG above. Using
   percentages (rather than fixed px) here is what lets it stay
   correctly aligned even as .cassetteSvg's own width changes
   (e.g. if you resize the cassette later) — the percentages are
   just the paper label rect's own x/y/width/height (14,12,92,18)
   divided by the SVG's full viewBox size (120,78).
   SAFE TO TWEAK: font-size, letter-spacing, color — freely.
   Changing the position/size percentages should only be needed if
   you also resize or reshape the paper label rect in the SVG. */
.mixtapeLabel{

    position:absolute;

    left:11.67%;

    top:15.38%;

    width:76.67%;

    height:23.08%;

    display:flex;

    align-items:center;

    justify-content:center;

    font-family:Georgia,serif;

    font-size:9px;

    letter-spacing:2px;

    color:#1a1a1a;

    pointer-events:none; /* clicks pass through to the button beneath */

}

/* the reels: spin forever, but only *visibly* while playing —
   see the note above about how .mixtape.playing controls this */
.reel{

    transform-box: fill-box;

    transform-origin: center;

    animation: reelSpin 3s linear infinite;

    animation-play-state: paused;

}
.mixtape.playing .reel{

    animation-play-state: running;

}
@keyframes reelSpin{

    to{ transform: rotate(360deg); }

}

.mixtapeControls{

    display:flex;

    gap:10px;

}
.mixtapeBtn{

    background:transparent;

    border:1px solid rgba(255,255,255,.25);

    color:#bcbcbc;

    font-size:11px;

    width:26px;

    height:22px;

    display:flex;

    align-items:center;

    justify-content:center;

    cursor:pointer;

    transition: all .2s ease;

}
.mixtapeBtn:hover{

    border-color: rgba(255,109,180,.6);

    color:#fff;

}

