M .gitignore => .gitignore +1 -0
@@ 1,1 1,2 @@
.claude/
+CLAUDE.md
D CLAUDE.md => CLAUDE.md +0 -88
@@ 1,88 0,0 @@
-# CLAUDE.md
-
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
-## Project Overview
-
-Realm is the visual exploration portal for cytrogen.icu. It replaces the root domain's previous blog with a Castlevania-inspired territory map. The blog lives at blog.cytrogen.icu.
-
-**Design language**: Deep cold tones (oklch blues), high-saturation orange as the sole accent, flat geometry, no strokes, no gradients, large color blocks.
-
-**Tech stack**: Pure HTML + CSS. Zero JavaScript. All SVG is inline. No build tools, no bundler, no framework.
-
-## Deployment
-
-Push-to-deploy via bare repo on VPS (accessible as `ssh vps-user`):
-
-```
-git push origin main
-```
-
-The post-receive hook at `~/repos/realm.git/hooks/post-receive` performs:
-1. Checkout to temp dir
-2. rsync to `/var/www/realm` (excludes `.git`, `caddy/`, `CLAUDE.md`)
-3. Push to local Sourcehut instance (`ssh://git@localhost:22222/~cytrogen/realm`)
-
-Caddy config lives at `/etc/caddy/Caddyfile` on the VPS (backup at `~/vps-deploy/Caddyfile`). Editing requires sudo. The `caddy/` directory in this repo contains reference snippets only.
-
-### VPS Infrastructure
-
-| Subdomain | Service | Backend |
-|---|---|---|
-| cytrogen.icu | Phase 1: 301 → blog.cytrogen.icu | Caddy redirect |
-| blog.cytrogen.icu | Hexo blog (static) | `/var/www/blog.cytrogen.icu` |
-| git.cytrogen.icu | Sourcehut git | localhost:5003 |
-| meta.cytrogen.icu | Sourcehut meta | localhost:5001 |
-| rss.cytrogen.icu | FreshRSS | localhost:8096 |
-| status.cytrogen.icu | Beszel | localhost:8090 |
-| mail.cytrogen.icu | Stalwart | localhost:8080 |
-
-Blog deploys via `~/repos/blog.git` → builds Hexo → `/var/www/blog.cytrogen.icu` → pushes to Sourcehut (`blog-local` + `blog-public`).
-
-## Architecture
-
-### CSS (`css/realm.css`)
-
-Single stylesheet using `@layer` for cascade control:
-```
-@layer reset, tokens, base, layout, components, utilities;
-```
-
-- **tokens**: oklch color variables, spacing, typography scales, motion durations on `:root`
-- **components**: SVG fill classes (`.svg-icon`, `.svg-interactive`), navigation, panels
-- Typed `@property` declarations at file top enable smooth color transitions on SVG fills
-- `prefers-reduced-motion` kills all transition durations globally
-
-Colors use oklch with relative color syntax (`oklch(from var(--accent) ...)`) for derived variants.
-
-### SVG Conventions
-
-All SVG assets are inline in the HTML DOM — never `<img>` or `<object>`.
-
-- Reusable shapes: `<symbol>` in a hidden sprite block, referenced via `<use href="#id">`
-- Decorative SVG: `aria-hidden="true" focusable="false"`
-- Informative SVG: `role="img" aria-labelledby="title-id"` with `<title>` as first child
-- Paths use CSS classes for fills — no inline `fill` attributes
-- No `stroke` attributes anywhere. No gradients. Fill-only flat geometry.
-- Use `viewBox` only — omit explicit `width`/`height` on `<symbol>` for responsive scaling
-
-### Page Structure
-
-- `index.html` — Realm entry, contains the SVG sprite `<defs>` block and navigation
-- `pages/contact.html` — 领地联络处 (Contact)
-- `caddy/` — Reference Caddyfile snippets (not deployed)
-
-## Migration Phases
-
-1. **Phase 1** (done): 301 redirect cytrogen.icu → blog.cytrogen.icu, blog files at `/var/www/blog.cytrogen.icu`
-2. **Phase 2** (current): CSS/SVG design system established in `css/realm.css`
-3. **Phase 3** (planned): Full scene layout — Castlevania-style layered environment or game-map navigation. CSS classes `.realm-scene`, `.realm-layer--far/mid/near` are pre-defined in the layout layer.
-4. **Phase 4** (planned): Realm goes live at cytrogen.icu root (serve from `/var/www/realm`), remove 301 redirects
-
-## Design Constraints
-
-- No JavaScript unless absolutely unavoidable
-- All interactivity via CSS (`:hover`, `:focus-visible`, transitions, `@property` animations)
-- SVG complexity must degrade gracefully — use container queries or media queries to hide detail at small sizes
-- Text-only fallback for terminals/Gemini-style access (planned: separate gopher/gemini protocol support)
-- Accessibility: skip decorative SVG via `aria-hidden`, label informative SVG, respect `prefers-reduced-motion`
A LICENSE => LICENSE +661 -0
@@ 0,0 1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<https://www.gnu.org/licenses/>.
R caddy/phase1-redirect.example.Caddyfile => caddy/phase4-live.example.Caddyfile +21 -22
@@ 1,12 1,27 @@
-# Phase 1: Blog migration — cytrogen.icu → blog.cytrogen.icu
+# Phase 4: Realm live — cytrogen.icu serves /var/www/cytrogen.icu
#
-# This is a reference copy of the redirect blocks deployed to /etc/caddy/Caddyfile.
-# The production Caddyfile also includes blocks for sourcehut, beszel, freshrss,
-# stalwart, etc. — only the realm-relevant portions are shown here.
+# This is a reference copy of the realm-relevant Caddy blocks deployed
+# to /etc/caddy/Caddyfile. The production Caddyfile also includes blocks
+# for sourcehut, beszel, freshrss, stalwart, etc.
#
-# Status: DEPLOYED 2026-02-27
+# Status: DEPLOYED 2026-03-04
-# Blog now served from /var/www/blog.cytrogen.icu
+# Realm portal
+cytrogen.icu, www.cytrogen.icu {
+ root * /var/www/cytrogen.icu
+ file_server
+ encode gzip
+
+ @static path *.css *.js *.jpg *.jpeg *.png *.gif *.ico *.svg *.webp *.woff *.woff2 *.ttf *.eot
+ header @static Cache-Control "public, max-age=2592000, immutable"
+
+ @html path *.html /
+ header @html Cache-Control "public, max-age=3600, must-revalidate"
+
+ try_files {path} {path}/ {path}.html
+}
+
+# Blog (unchanged from Phase 1)
blog.cytrogen.icu {
root * /var/www/blog.cytrogen.icu
file_server
@@ 33,19 48,3 @@ blog.cytrogen.icu {
try_files {path} {path}/ {path}.html
}
-
-# 301 permanent redirect — root domain to blog subdomain
-cytrogen.icu, www.cytrogen.icu {
- header Link `<https://blog.cytrogen.icu{uri}>; rel="canonical"`
- header X-Robots-Tag "noindex, nofollow"
- redir https://blog.cytrogen.icu{uri} permanent
-}
-
-# Phase 4: Replace the redirect block above with:
-#
-# cytrogen.icu, www.cytrogen.icu {
-# root * /var/www/realm
-# file_server
-# encode gzip
-# try_files {path} {path}/ {path}.html
-# }
M css/realm.css => css/realm.css +1026 -22
@@ 16,7 16,7 @@
@property --fill-current {
syntax: "<color>";
inherits: true;
- initial-value: oklch(0.85 0.02 240);
+ initial-value: oklch(0.85 0.02 280);
}
@property --fill-accent {
@@ 26,6 26,48 @@
}
/* ================================================================
+ KEYFRAMES — skull opening animation
+ ================================================================ */
+
+@keyframes skull-split-up {
+ 0%, 30% { transform: translateY(0); }
+ 100% { transform: translateY(-110%); }
+}
+
+@keyframes skull-split-down {
+ 0%, 30% { transform: translateY(0); }
+ 100% { transform: translateY(110%); }
+}
+
+@keyframes wall-fade {
+ 0%, 99% { visibility: visible; }
+ 100% { visibility: hidden; }
+}
+
+@keyframes lock-shake {
+ 0%, 100% { transform: rotate(0deg); }
+ 15% { transform: rotate(-10deg); }
+ 30% { transform: rotate(10deg); }
+ 45% { transform: rotate(-7deg); }
+ 60% { transform: rotate(7deg); }
+ 75% { transform: rotate(-3deg); }
+ 90% { transform: rotate(3deg); }
+}
+
+@keyframes lock-text-appear {
+ 0% { opacity: 0; transform: translateY(0); }
+ 12% { opacity: 1; transform: translateY(-8px); }
+ 65% { opacity: 1; transform: translateY(-8px); }
+ 100% { opacity: 0; transform: translateY(-14px); }
+}
+
+@keyframes forge-pulse {
+ 0%, 100% { opacity: 0.25; }
+ 50% { opacity: 0.4; }
+}
+
+
+/* ================================================================
RESET
================================================================ */
@@ 67,16 109,16 @@
@layer tokens {
:root {
/* === Background scale (deep cold) === */
- --bg-abyss: oklch(0.10 0.02 260);
- --bg-deep: oklch(0.15 0.03 255);
- --bg-mid: oklch(0.22 0.04 250);
- --bg-surface: oklch(0.28 0.04 245);
- --bg-elevated: oklch(0.35 0.04 240);
+ --bg-abyss: oklch(0.10 0.02 290);
+ --bg-deep: oklch(0.15 0.03 285);
+ --bg-mid: oklch(0.22 0.04 280);
+ --bg-surface: oklch(0.28 0.04 278);
+ --bg-elevated: oklch(0.35 0.04 275);
/* === Text scale === */
- --text-primary: oklch(0.85 0.02 240);
- --text-secondary: oklch(0.60 0.03 250);
- --text-dim: oklch(0.42 0.03 255);
+ --text-primary: oklch(0.85 0.02 280);
+ --text-secondary: oklch(0.60 0.03 280);
+ --text-dim: oklch(0.42 0.03 285);
/* === Accent: high-saturation orange (sole emphasis) === */
--accent: oklch(0.72 0.18 55);
@@ 166,13 208,25 @@
================================================================ */
@layer layout {
+ /* --- Page-level layout (used on sub-pages) --- */
.realm {
- display: grid;
- place-items: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
min-height: 100dvh;
padding: var(--space-lg);
}
+ /* --- Folder layout (index page) --- */
+ .realm-folder {
+ width: 100%;
+ margin-inline: auto;
+ height: 100dvh;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ }
+
.realm-container {
width: 100%;
max-width: 72rem;
@@ 180,15 234,54 @@
padding-inline: var(--space-md);
}
- /* Phase 3 scene viewport — reserves full-screen space */
- .realm-scene {
- position: relative;
+ /* --- Skull overlay --- */
+ .skull-overlay {
+ position: fixed;
+ inset: 0;
+ z-index: 100;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: transparent;
+ pointer-events: none;
+ animation: wall-fade 2.5s var(--ease-out) forwards;
+ }
+
+ .skull-overlay .skull {
width: 100%;
- min-height: 100dvh;
+ height: 100%;
+ }
+
+ .skull-top {
+ animation: skull-split-up 2.5s var(--ease-out) forwards;
+ }
+
+ .skull-bottom {
+ animation: skull-split-down 2.5s var(--ease-out) forwards;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ .skull-overlay {
+ display: none;
+ }
+ }
+
+ /* --- Folder content area --- */
+ .folder-content {
+ flex: 1;
+ background: var(--bg-deep);
+ min-height: 0;
overflow: hidden;
+ container-type: inline-size;
}
- /* Scene depth layers (Phase 3) */
+ /* --- Scene SVG --- */
+ .folder-content svg {
+ width: 100%;
+ height: 100%;
+ }
+
+ /* --- Scene depth layers (compositing within a scene) --- */
.realm-layer {
position: absolute;
inset: 0;
@@ 200,6 293,50 @@
.realm-layer--mid { z-index: 2; }
.realm-layer--near { z-index: 3; }
.realm-layer--ui { z-index: 10; }
+
+ /* --- Scene container (close-up pages: unified viewport lock) --- */
+
+ .realm-scene {
+ width: 100%;
+ height: 100dvh;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background: var(--bg-abyss);
+ }
+
+ .realm-scene__content {
+ flex: 1;
+ min-height: 0;
+ width: 100%;
+ max-width: var(--scene-max-width, 56rem);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-inline: var(--space-lg);
+ }
+
+ .realm-scene__backdrop {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: var(--scene-bg, var(--bg-abyss));
+ }
+
+ .realm-scene__backdrop > svg {
+ max-width: 100%;
+ max-height: 100%;
+ width: auto;
+ height: auto;
+ }
+
+ .realm-scene__nav {
+ flex-shrink: 0;
+ padding-block: var(--space-md);
+ }
}
/* ================================================================
@@ 305,17 442,884 @@
fill: var(--text-dim);
}
- /* --- Card / Panel --- */
+ /* --- Scene Hotspots --- */
+
+ .hotspot {
+ cursor: pointer;
+ }
+
+ .hotspot .hotspot-shape {
+ fill: var(--bg-surface);
+ transition: fill var(--duration-normal) var(--ease-default);
+ }
+
+ .hotspot .fill-path {
+ fill: oklch(0.20 0.03 275);
+ }
+
+ .hotspot:hover .hotspot-shape,
+ .hotspot:focus-visible .hotspot-shape {
+ fill: var(--accent);
+ }
+
+ .hotspot .hotspot-icon {
+ fill: var(--text-dim);
+ transition: fill var(--duration-normal) var(--ease-default);
+ }
+
+ .hotspot:hover .hotspot-icon,
+ .hotspot:focus-visible .hotspot-icon {
+ fill: var(--bg-abyss);
+ }
+
+ .hotspot:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+
+ /* Hotspot tooltip via CSS */
+ .hotspot .hotspot-label {
+ fill: var(--text-dim);
+ font-family: var(--font-body);
+ font-size: 11px;
+ opacity: 0;
+ transition: opacity var(--duration-normal) var(--ease-default);
+ }
+
+ .hotspot:hover .hotspot-label,
+ .hotspot:focus-visible .hotspot-label {
+ opacity: 1;
+ fill: var(--accent-bright);
+ }
+
+ /* Map-board labels: always visible (no tooltip opacity) */
+ .hotspot .map-label {
+ fill: var(--text-dim);
+ font-family: var(--font-body);
+ font-size: 11px;
+ transition: fill var(--duration-normal) var(--ease-default);
+ }
+
+ .hotspot:hover .map-label,
+ .hotspot:focus-visible .map-label {
+ fill: var(--accent-bright);
+ }
+
+ /* --- Scene fill classes --- */
+
+ .fill-sky { fill: oklch(0.12 0.03 290); }
+ .fill-mountain { fill: oklch(0.16 0.03 285); }
+ .fill-mountain-far { fill: oklch(0.13 0.025 288); }
+ .fill-ground { fill: oklch(0.18 0.035 280); }
+ .fill-wall { fill: oklch(0.25 0.04 278); }
+ .fill-wall-dark { fill: oklch(0.20 0.035 280); }
+ .fill-wall-light { fill: oklch(0.30 0.04 275); }
+ .fill-roof { fill: oklch(0.18 0.04 282); }
+ .fill-window { fill: oklch(from var(--accent) l c h / 0.5); }
+ .fill-window-glow { fill: oklch(from var(--accent) l c h / 0.25); }
+ .fill-door { fill: oklch(0.08 0.02 290); }
+ .fill-moon { fill: oklch(0.85 0.02 280); }
+ .fill-star { fill: oklch(0.70 0.02 280); }
+ .fill-path { fill: oklch(0.20 0.03 275); }
+ .fill-tree { fill: oklch(0.14 0.04 285); }
+ .fill-board { fill: var(--bg-elevated); }
+ .fill-accent-shape { fill: var(--accent); }
+ .fill-accent-dim { fill: var(--accent-dim); }
+
+ /* --- Skull SVG fills --- */
+ .fill-skull { fill: oklch(0.25 0.04 280); }
+ .fill-skull-eye { fill: var(--accent); }
+
+ /* --- Scene title text --- */
+ .scene-title {
+ fill: var(--text-dim);
+ font-family: var(--font-body);
+ font-size: 14px;
+ letter-spacing: 0.1em;
+ }
+
+ /* --- Notice Board --- */
+
+ .notice-board {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ max-width: 56rem;
+ width: 100%;
+ margin-inline: auto;
+ margin-block-end: var(--space-lg);
+ }
+
+ .notice-board__frame {
+ background: var(--bg-elevated);
+ padding: var(--space-md);
+ width: 100%;
+ }
+
+ .notice-board__title {
+ font-size: var(--text-lg);
+ letter-spacing: 0.1em;
+ color: var(--accent);
+ text-align: center;
+ padding-block-end: var(--space-md);
+ }
+
+ .notice-board__surface {
+ background: var(--bg-mid);
+ padding: var(--space-lg);
+ max-height: 60vh;
+ overflow-y: auto;
+ }
+
+ .notice-board__surface h2 {
+ font-size: var(--text-base);
+ color: var(--accent-dim);
+ margin-block: var(--space-lg) var(--space-sm);
+ }
+
+ .notice-board__surface h2:first-child {
+ margin-block-start: 0;
+ }
+
+ .notice-board__surface p {
+ margin-block-end: var(--space-md);
+ }
+
+ .notice-board__surface ul {
+ margin-block-end: var(--space-md);
+ padding-inline-start: var(--space-lg);
+ list-style: disc;
+ color: var(--text-secondary);
+ }
+
+ .notice-board__surface li {
+ margin-block-end: var(--space-xs);
+ }
+
+ .notice-board__post {
+ width: 4rem;
+ height: 12rem;
+ background: var(--bg-elevated);
+ }
+
+ .notice-board__ground {
+ width: 100%;
+ margin-block-start: -1rem;
+ }
+
+ .notice-board__ground svg {
+ display: block;
+ width: 100%;
+ height: auto;
+ }
+
+ .notice-board__surface::-webkit-scrollbar {
+ width: 6px;
+ }
- .realm-panel {
+ .notice-board__surface::-webkit-scrollbar-track {
+ background: var(--bg-deep);
+ }
+
+ .notice-board__surface::-webkit-scrollbar-thumb {
background: var(--bg-surface);
+ }
+
+ /* --- Scroll (卷轴) --- */
+
+ .scroll {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ max-width: 56rem;
+ width: 100%;
+ margin-inline: auto;
+ }
+
+ .scroll__rod {
+ width: calc(100% + 2rem);
+ height: 0.75rem;
+ background: var(--bg-elevated);
+ border-radius: 0.375rem;
+ position: relative;
+ flex-shrink: 0;
+ }
+
+ .scroll__rod::before,
+ .scroll__rod::after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ translate: 0 -50%;
+ width: 1.25rem;
+ height: 1.25rem;
+ background: var(--bg-elevated);
+ border-radius: 50%;
+ }
+
+ .scroll__rod::before { left: -0.375rem; }
+ .scroll__rod::after { right: -0.375rem; }
+
+ .scroll__body {
padding: var(--space-lg);
- container-type: inline-size;
+ max-height: 60vh;
+ overflow-y: auto;
+ width: 100%;
+ background: var(--bg-surface);
+ }
+
+ .scroll__title {
+ font-size: var(--text-lg);
+ letter-spacing: 0.1em;
+ color: var(--accent);
+ text-align: center;
+ padding-block-end: var(--space-md);
+ }
+
+ .scroll__body h2 {
+ font-size: var(--text-base);
+ color: var(--accent-dim);
+ margin-block: var(--space-lg) var(--space-sm);
+ }
+
+ .scroll__body h2:first-of-type {
+ margin-block-start: 0;
+ }
+
+ .scroll__body p {
+ margin-block-end: var(--space-md);
+ }
+
+ .scroll__body ul {
+ margin-block-end: var(--space-md);
+ padding-inline-start: var(--space-lg);
+ list-style: disc;
+ color: var(--text-secondary);
+ }
+
+ .scroll__body li {
+ margin-block-end: var(--space-xs);
+ }
+
+ .scroll__body::-webkit-scrollbar {
+ width: 6px;
+ }
+
+ .scroll__body::-webkit-scrollbar-track {
+ background: transparent;
+ }
+
+ .scroll__body::-webkit-scrollbar-thumb {
+ background: var(--bg-surface);
+ }
+
+ /* --- Card / Panel --- */
+
+ .realm-content {
+ max-width: 40rem;
+ width: 100%;
+ }
+
+ /* --- Capsule Panel (:target overlay) --- */
+
+ .capsule-panel {
+ position: fixed;
+ inset: 0;
+ z-index: 10;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: oklch(0.05 0.02 290 / 0.92);
+ opacity: 0;
+ visibility: hidden;
+ transition:
+ opacity var(--duration-normal) var(--ease-default),
+ visibility var(--duration-normal) var(--ease-default);
+ }
+
+ .capsule-panel:target {
+ opacity: 1;
+ visibility: visible;
}
- @container (min-width: 30rem) {
- .realm-panel {
- padding: var(--space-xl);
+ .capsule-panel .notice-board {
+ max-height: 80vh;
+ overflow-y: auto;
+ }
+
+ .capsule-panel .scroll {
+ max-width: min(90vw, 56rem);
+ padding-inline: var(--space-md);
+ }
+
+ .capsule-panel__close {
+ margin-block-start: var(--space-md);
+ color: var(--text-secondary);
+ font-size: var(--text-sm);
+ text-decoration: none;
+ transition: color var(--duration-normal) var(--ease-default);
+ min-width: 44px;
+ min-height: 44px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .capsule-panel__close:hover,
+ .capsule-panel__close:focus-visible {
+ color: var(--accent);
+ }
+
+ /* --- Close-up SVG panels (colophon :has(:target)) --- */
+
+ /* Keep panel visible when a descendant is :target */
+ .capsule-panel:has(:target) {
+ opacity: 1;
+ visibility: visible;
+ }
+
+ /* Close-up SVG sizing */
+ .closeup {
+ width: min(90vw, 56rem);
+ max-height: 80vh;
+ display: block;
+ }
+
+ /* Interactive items within close-up */
+ .closeup-item { cursor: pointer; }
+
+ .closeup-item__shape {
+ fill: var(--bg-surface);
+ transition: fill var(--duration-normal) var(--ease-default);
+ }
+ .closeup-item:hover .closeup-item__shape { fill: var(--accent); }
+ .closeup-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
+
+ .closeup-item__name {
+ fill: var(--text-dim);
+ font-family: var(--font-body);
+ font-size: 12px;
+ transition: fill var(--duration-normal) var(--ease-default);
+ }
+ .closeup-item:hover .closeup-item__name { fill: var(--accent-bright); }
+
+ /* Description card — hidden by default, shown when parent <g> is :target */
+ .closeup-desc {
+ opacity: 0;
+ transition: opacity var(--duration-normal) var(--ease-default);
+ pointer-events: none;
+ }
+ :target > .closeup-desc {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ .closeup-desc__bg { fill: var(--bg-deep); }
+ .closeup-desc__label { fill: var(--accent); font-family: var(--font-body); font-size: 14px; }
+ .closeup-desc__text { fill: var(--text-secondary); font-family: var(--font-body); font-size: 13px; }
+
+ /* Panel header text inside SVG */
+ .closeup-title { fill: var(--accent); font-family: var(--font-body); font-size: 18px; letter-spacing: 0.1em; }
+
+ /* Forge: dim non-targeted flames when one is selected */
+ .closeup--forge .closeup-item {
+ transition: opacity var(--duration-normal) var(--ease-default);
+ }
+ .closeup--forge:has(:target) .closeup-item:not(:target) {
+ opacity: 0.15;
+ }
+
+ /* Fire depth fills — graduated brightness (front=bright, back=dim) */
+ /* Layer 1 (front): reuses fill-window-glow / fill-window / fill-accent-shape */
+ .fill-fire-2-glow { fill: oklch(from var(--accent) calc(l - 0.06) c h / 0.2); }
+ .fill-fire-2-body { fill: oklch(from var(--accent) calc(l - 0.06) c h / 0.4); }
+ .fill-fire-2-core { fill: oklch(from var(--accent) calc(l - 0.06) c h); }
+ .fill-fire-3-glow { fill: oklch(from var(--accent) calc(l - 0.12) c h / 0.15); }
+ .fill-fire-3-body { fill: oklch(from var(--accent) calc(l - 0.12) c h / 0.3); }
+ .fill-fire-3-core { fill: oklch(from var(--accent) calc(l - 0.12) c h); }
+ .fill-fire-4-glow { fill: oklch(from var(--accent) calc(l - 0.2) c h / 0.1); }
+ .fill-fire-4-body { fill: oklch(from var(--accent) calc(l - 0.2) c h / 0.2); }
+ .fill-fire-4-core { fill: oklch(from var(--accent) calc(l - 0.2) c h); }
+
+ /* --- Capsule Lock (room padlock animation) --- */
+
+ .capsule-lock {
+ transform-box: fill-box;
+ transform-origin: center bottom;
+ }
+
+ .capsule-lock-text {
+ fill: var(--accent);
+ font-family: var(--font-body);
+ font-size: 11px;
+ opacity: 0;
+ }
+
+ :target > .capsule-lock {
+ animation: lock-shake 0.6s var(--ease-default);
+ }
+
+ :target > .capsule-lock-text {
+ animation: lock-text-appear 3s var(--ease-default) forwards;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ :target > .capsule-lock {
+ animation: none;
+ }
+ :target > .capsule-lock-text {
+ animation: none;
+ opacity: 1;
+ }
+ }
+
+ /* --- Forge Glow (工坊炉火) --- */
+
+ .forge-glow {
+ animation: forge-pulse 3s var(--ease-default) infinite;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ .forge-glow { animation: none; }
+ }
+
+ /* --- Phone Scene (联络处场景容器) --- */
+
+ .phone-scene {
+ background: oklch(0.25 0.04 278);
+ width: min(95%, 56rem);
+ min-height: 80dvh;
+ margin-inline: auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: var(--space-xl) var(--space-lg);
+ }
+
+ /* --- Phone Booth (联络处) --- */
+
+ .phone-booth {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: var(--space-lg);
+ flex-wrap: wrap;
+ }
+
+ /* Note stack: two stacked notes */
+
+ .phone-note-stack {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ align-self: flex-start;
+ clip-path: inset(0 -2rem -200vh -2rem);
+ padding-block-end: var(--space-md);
+ }
+
+ /* Dial guide note */
+
+ .phone-note {
+ background: var(--bg-surface);
+ padding: var(--space-md) var(--space-lg);
+ width: 18rem;
+ position: relative;
+ z-index: 2;
+ }
+
+ .phone-note__title {
+ color: var(--accent);
+ font-size: var(--text-base);
+ letter-spacing: 0.05em;
+ margin-block-end: var(--space-sm);
+ }
+
+ .phone-note__list {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ gap: var(--space-xs) var(--space-sm);
+ }
+
+ .phone-note__list dt {
+ color: var(--accent-bright);
+ font-family: var(--font-mono);
+ font-size: var(--text-base);
+ }
+
+ .phone-note__list dd {
+ color: var(--text-secondary);
+ font-size: var(--text-base);
+ }
+
+ /* Hidden hint note (checkbox hack) */
+
+ .phone-hint-toggle {
+ position: absolute;
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ .phone-hint {
+ background: var(--bg-elevated);
+ padding: var(--space-xs) var(--space-md);
+ width: 11rem;
+ margin-block-start: -14rem;
+ transform: rotate(5deg);
+ position: relative;
+ z-index: 1;
+ transition: transform var(--duration-slow) var(--ease-out);
+ }
+
+ .phone-hint__tab {
+ display: block;
+ cursor: pointer;
+ color: var(--accent);
+ font-size: var(--text-sm);
+ text-align: center;
+ line-height: 2rem;
+ user-select: none;
+ }
+
+ .phone-hint__tab:hover {
+ color: var(--accent-bright);
+ }
+
+ .phone-hint__body {
+ padding-block-start: var(--space-sm);
+ color: var(--text-secondary);
+ font-size: var(--text-sm);
+ line-height: 1.8;
+ }
+
+ .phone-hint__body ol {
+ list-style: decimal;
+ padding-inline-start: var(--space-md);
+ }
+
+ .phone-hint__body li {
+ margin-block-end: var(--space-xs);
+ }
+
+ .phone-hint-toggle:checked ~ .phone-hint {
+ transform: translateY(calc(14rem + var(--space-xs))) rotate(5deg);
+ }
+
+ .phone-hint-toggle:focus-visible ~ .phone-hint .phone-hint__tab {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ .phone-hint {
+ transition: none;
+ }
+ }
+
+ /* Phone unit */
+
+ .phone {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ width: clamp(18rem, 50vw, 24rem);
+ }
+
+ /* Hood (canopy) */
+ .phone-hood {
+ background: var(--text-dim);
+ height: 1.25rem;
+ margin-inline: calc(-1 * var(--space-md));
+ position: relative;
+ }
+
+ .phone-hood::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: var(--bg-elevated);
+ }
+
+ /* Body */
+ .phone-body {
+ position: relative;
+ background: var(--bg-surface);
+ padding: var(--space-md);
+ padding-inline-start: calc(var(--space-md) + 3rem);
+ }
+
+ /* Shelf */
+ .phone-shelf {
+ background: var(--text-dim);
+ height: 0.75rem;
+ margin-inline: calc(-1 * var(--space-md));
+ position: relative;
+ }
+
+ .phone-shelf::before {
+ content: '';
+ position: absolute;
+ left: 50%;
+ translate: -50% 0;
+ bottom: 100%;
+ width: 0;
+ height: 0;
+ border-left: 0.5rem solid transparent;
+ border-right: 0.5rem solid transparent;
+ border-bottom: 0.5rem solid var(--text-dim);
+ }
+
+ /* Coin slot */
+ .phone-coin {
+ width: 50%;
+ margin-inline: auto;
+ margin-block: var(--space-sm);
+ height: 0.5rem;
+ background: var(--bg-deep);
+ border-top: 2px solid var(--bg-mid);
+ border-bottom: 2px solid var(--bg-mid);
+ }
+
+ /* Handset */
+ .phone-handset {
+ position: absolute;
+ left: var(--space-sm);
+ top: calc(var(--space-md) - 1rem);
+ width: 1.5rem;
+ height: 3.5rem;
+ background: var(--text-dim);
+ border: none;
+ cursor: pointer;
+ z-index: 1;
+ transition: transform var(--duration-normal) var(--ease-out);
+ }
+
+ /* T-shape: earpiece */
+ .phone-handset::before {
+ content: '';
+ position: absolute;
+ top: -0.25rem;
+ left: -0.375rem;
+ width: 2.25rem;
+ height: 0.75rem;
+ background: var(--text-dim);
+ border-radius: 0.25rem 0.25rem 0 0;
+ }
+
+ /* T-shape: mouthpiece */
+ .phone-handset::after {
+ content: '';
+ position: absolute;
+ bottom: -0.25rem;
+ left: -0.375rem;
+ width: 2.25rem;
+ height: 0.75rem;
+ background: var(--text-dim);
+ border-radius: 0 0 0.25rem 0.25rem;
+ }
+
+ .phone-handset:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+
+ .phone[data-state="idle"] .phone-handset {
+ transform: none;
+ }
+
+ .phone:not([data-state="idle"]) .phone-handset {
+ transform: translateY(-2rem) rotate(-15deg);
+ }
+
+ /* Keypad */
+ .phone-keypad {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 3px;
+ transition: opacity var(--duration-normal) var(--ease-default);
+ }
+
+ .phone-key {
+ background: var(--bg-elevated);
+ border: none;
+ color: var(--text-primary);
+ font-family: var(--font-mono);
+ font-size: var(--text-base);
+ padding: var(--space-sm) 0;
+ cursor: pointer;
+ transition: background var(--duration-fast) var(--ease-default);
+ }
+
+ .phone-key:hover {
+ background: var(--accent-dim);
+ }
+
+ .phone-key:active {
+ background: var(--accent);
+ }
+
+ .phone-key:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: -2px;
+ }
+
+ /* Keypad state: disabled when not ready */
+ .phone[data-state="idle"] .phone-keypad,
+ .phone[data-state="connecting"] .phone-keypad,
+ .phone[data-state="connected"] .phone-keypad,
+ .phone[data-state="error"] .phone-keypad {
+ pointer-events: none;
+ opacity: 0.3;
+ }
+
+ .phone[data-state="ready"] .phone-keypad {
+ pointer-events: auto;
+ opacity: 1;
+ }
+
+ /* Display */
+ .phone-display {
+ background: var(--bg-abyss);
+ color: var(--accent);
+ font-family: var(--font-mono);
+ padding: var(--space-sm) var(--space-md);
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ min-height: 5.5rem;
+ box-shadow: inset 0 0 0 2px var(--bg-deep);
+ }
+
+ .phone-display__digits {
+ font-size: var(--text-lg);
+ letter-spacing: 0.2em;
+ min-height: 1.4em;
+ }
+
+ .phone-display__status {
+ font-size: var(--text-sm);
+ color: var(--text-dim);
+ }
+
+ /* Result (shown inside display) */
+ .phone-result {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .phone-result__link {
+ color: var(--accent-bright);
+ font-family: var(--font-mono);
+ font-size: var(--text-sm);
+ }
+
+ .phone-result__link:hover,
+ .phone-result__link:focus-visible {
+ color: var(--accent);
+ text-decoration: underline;
+ }
+
+ /* --- Skip Link (keyboard/screen reader shortcut) --- */
+
+ .skip-link {
+ position: absolute;
+ width: 1px; height: 1px;
+ padding: 0; margin: -1px;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ white-space: nowrap; border: 0;
+ z-index: 200;
+ background: var(--bg-abyss);
+ color: var(--accent);
+ font-size: var(--text-base);
+ text-decoration: none;
+ }
+
+ .skip-link:focus {
+ position: fixed;
+ top: var(--space-sm); left: var(--space-sm);
+ width: auto; height: auto;
+ padding: var(--space-sm) var(--space-md);
+ clip: auto; overflow: visible;
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+
+ /* --- Screen Reader Navigation (always visually hidden) --- */
+
+ .scene-nav {
+ position: absolute;
+ width: 1px; height: 1px;
+ padding: 0; margin: -1px;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ white-space: nowrap; border: 0;
+ }
+
+ .scene-nav__list {
+ list-style: none;
+ padding: 0; margin: 0;
+ }
+
+ .scene-nav__link {
+ display: block;
+ padding: var(--space-xs);
+ color: var(--text-secondary);
+ }
+
+ a.scene-nav__link:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+
+ .scene-nav__link--locked {
+ color: var(--text-dim);
+ }
+
+ /* --- Touch Hitarea Expansion --- */
+
+ .hotspot-hitarea {
+ fill-opacity: 0;
+ pointer-events: all;
+ }
+
+ /* --- realm-scene context overrides --- */
+
+ .realm-scene .phone-scene {
+ width: 100%;
+ min-height: 0;
+ height: 100%;
+ }
+
+ .realm-scene .notice-board {
+ max-height: 100%;
+ overflow: hidden;
+ }
+
+ .realm-scene .notice-board__frame {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .realm-scene .notice-board__surface {
+ max-height: none;
+ flex: 1;
+ min-height: 0;
+ }
+
+ /* --- Responsive scene rules --- */
+
+ @container (max-width: 25rem) {
+ .scene-detail {
+ display: none;
}
}
}
M index.html => index.html +232 -71
@@ 1,93 1,254 @@
<!DOCTYPE html>
-<html lang="en">
+<html lang="zh-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Realm — cytrogen.icu</title>
<meta name="description" content="Realm — the visual exploration territory of cytrogen.icu">
<meta name="theme-color" content="#1a1a2e">
- <link rel="stylesheet" href="/css/realm.css">
+ <link rel="stylesheet" href="css/realm.css">
</head>
<body>
+ <a class="skip-link" href="#scene-nav-exterior">跳过场景</a>
+
<!-- ============================================================
- SVG Sprite Definitions (hidden from rendering and AT)
- All reusable symbols defined here, referenced via <use href>
+ Skull Opening Animation Overlay
+ Demon skull splits open to reveal the realm.
+ aria-hidden: purely decorative, not for screen readers.
============================================================ -->
- <svg aria-hidden="true" focusable="false" style="position:absolute;width:0;height:0;overflow:hidden">
- <defs>
- <!-- Realm Sigil: geometric castle tower silhouette -->
- <symbol id="sigil-tower" viewBox="0 0 120 160">
- <path class="svg-icon" d="
- M60 0 L70 20 H80 V40 H90 V60 H100 V160 H20 V60 H30 V40 H40 V20 H50 Z
+ <div class="skull-overlay" aria-hidden="true">
+ <svg class="skull" viewBox="-200 -250 800 1000" preserveAspectRatio="xMidYMid slice">
+ <!-- Lower half: wall only, renders first (behind skull) -->
+ <g class="skull-bottom">
+ <!-- Wall background -->
+ <rect class="fill-wall-dark" x="-200" y="250" width="800" height="500"/>
+ </g>
+
+ <!-- Upper half: goat skull, rises with the wall (renders last = on top) -->
+ <g class="skull-top">
+ <!-- Wall background -->
+ <rect class="fill-wall-dark" x="-200" y="-250" width="800" height="500"/>
+ <!-- Goat skull silhouette -->
+ <path class="fill-skull" d="
+ M175 380 L158 340 L138 290 L125 245
+ L130 200 L155 170 L200 158
+ L245 170 L270 200 L275 245
+ L262 290 L242 340 L225 380 Z
"/>
- <rect class="svg-icon" x="50" y="100" width="20" height="60"/>
- <rect class="svg-icon--accent" x="45" y="70" width="10" height="15"/>
- <rect class="svg-icon--accent" x="65" y="70" width="10" height="15"/>
- <rect class="svg-icon--accent" x="55" y="50" width="10" height="10"/>
- </symbol>
-
- <!-- Navigation arrow: right-pointing chevron -->
- <symbol id="icon-arrow" viewBox="0 0 24 24">
- <path class="svg-icon" d="M8 4 L18 12 L8 20 Z"/>
- </symbol>
-
- <!-- Decorative divider: geometric battlement pattern -->
- <symbol id="divider-battlement" viewBox="0 0 200 12">
- <path class="svg-icon" d="
- M0 12 V6 H10 V0 H20 V6 H30 V0 H40 V6 H50 V0 H60 V6
- H70 V0 H80 V6 H90 V0 H100 V6 H110 V0 H120 V6
- H130 V0 H140 V6 H150 V0 H160 V6 H170 V0 H180 V6
- H190 V0 H200 V6 V12 Z
+ <!-- Left horn -->
+ <path class="fill-skull" d="
+ M130 205 Q70 170 35 110
+ L65 95 Q85 145 145 180 Z
"/>
- </symbol>
-
- <!-- Side door icon: arched doorway -->
- <symbol id="icon-door" viewBox="0 0 40 60">
- <path class="svg-icon" d="
- M0 60 V15 Q0 0 20 0 Q40 0 40 15 V60 Z
+ <!-- Right horn -->
+ <path class="fill-skull" d="
+ M270 205 Q330 170 365 110
+ L335 95 Q315 145 255 180 Z
+ "/>
+ <!-- Left eye socket -->
+ <path class="fill-skull-eye" d="
+ M140 245 L168 238 L172 268 L148 278 Z
"/>
- <circle class="svg-icon--accent" cx="28" cy="35" r="2.5"/>
- </symbol>
- </defs>
- </svg>
-
- <main class="realm">
- <!-- Sigil and title -->
- <header class="realm-sigil">
- <svg role="img" aria-labelledby="sigil-title" width="120" height="160">
- <title id="sigil-title">Realm sigil — a castle tower</title>
- <use href="#sigil-tower"/>
- </svg>
- <h1 class="realm-sigil__title">Realm</h1>
- <p class="realm-sigil__subtitle">cytrogen.icu</p>
- </header>
-
- <!-- Divider -->
- <svg class="realm-divider" aria-hidden="true" focusable="false">
- <use href="#divider-battlement"/>
+ <!-- Right eye socket -->
+ <path class="fill-skull-eye" d="
+ M232 238 L260 245 L252 278 L228 268 Z
+ "/>
+ <!-- Left nostril -->
+ <path class="fill-skull-eye" d="
+ M182 325 L190 313 L194 330 L187 348 Z
+ "/>
+ <!-- Right nostril -->
+ <path class="fill-skull-eye" d="
+ M210 313 L218 325 L213 348 L206 330 Z
+ "/>
+ </g>
</svg>
+ </div>
- <!-- Navigation: realm destinations -->
- <nav class="realm-nav" aria-label="Realm navigation">
- <a href="https://blog.cytrogen.icu">
- <svg aria-hidden="true" focusable="false" width="20" height="20">
- <use href="#icon-door"/>
- </svg>
- 城堡入口 — Blog
- </a>
- <a href="/pages/contact.html">
- <svg aria-hidden="true" focusable="false" width="16" height="16">
- <use href="#icon-arrow"/>
+ <!-- ============================================================
+ Main Folder Layout
+ ============================================================ -->
+ <main class="realm-folder">
+ <h1 class="visually-hidden">城堡外观</h1>
+
+ <!-- Folder Content -->
+ <div class="folder-content">
+
+ <!-- ======================================================
+ Castle Exterior (城堡外观)
+ ====================================================== -->
+ <svg role="group" aria-labelledby="scene-exterior-title" viewBox="0 0 800 500">
+ <title id="scene-exterior-title">城堡外观 — Castle exterior scene with gate, contact phone, notice board, and grave</title>
+
+ <!-- Sky -->
+ <rect class="fill-sky" x="0" y="0" width="800" height="500"/>
+
+ <!-- Stars (decorative detail) -->
+ <g class="scene-detail" aria-hidden="true">
+ <rect class="fill-star" x="80" y="30" width="3" height="3"/>
+ <rect class="fill-star" x="200" y="55" width="2" height="2"/>
+ <rect class="fill-star" x="350" y="20" width="3" height="3"/>
+ <rect class="fill-star" x="520" y="45" width="2" height="2"/>
+ <rect class="fill-star" x="680" y="25" width="3" height="3"/>
+ <rect class="fill-star" x="740" y="60" width="2" height="2"/>
+ <rect class="fill-star" x="150" y="80" width="2" height="2"/>
+ <rect class="fill-star" x="600" y="70" width="2" height="2"/>
+ </g>
+
+ <!-- Moon -->
+ <circle class="fill-moon" cx="680" cy="80" r="30" aria-hidden="true"/>
+ <circle class="fill-sky" cx="695" cy="70" r="28" aria-hidden="true"/>
+
+ <!-- Distant mountains -->
+ <path class="fill-mountain-far" d="M0 280 L100 180 L200 240 L320 160 L440 220 L540 170 L650 230 L750 190 L800 220 L800 320 L0 320 Z" aria-hidden="true"/>
+ <path class="fill-mountain" d="M0 310 L80 250 L180 290 L280 230 L380 270 L500 220 L600 280 L700 250 L800 290 L800 340 L0 340 Z" aria-hidden="true"/>
+
+ <!-- Ground -->
+ <rect class="fill-ground" x="0" y="330" width="800" height="170"/>
+
+ <!-- === HOTSPOT: Road → Neighboring Lands === -->
+ <a class="hotspot" href="pages/neighbors.html" aria-label="邻邦 — Neighboring lands">
+ <title>邻邦 — Neighboring lands</title>
+ <path class="hotspot-shape fill-path" d="M350 500 L450 500 L438 380 L362 380 Z"/>
+ <text class="hotspot-label" x="400" y="470" text-anchor="middle">走</text>
+ </a>
+
+ <!-- Castle main wall -->
+ <rect class="fill-wall" x="150" y="200" width="500" height="180"/>
+
+ <!-- Castle battlements -->
+ <path class="fill-wall" d="
+ M150 200 L150 180 L180 180 L180 170 L210 170 L210 180 L240 180 L240 170 L270 170 L270 180
+ L300 180 L300 170 L330 170 L330 180 L360 180 L360 170 L390 170 L390 180
+ L420 180 L420 170 L450 170 L450 180 L480 180 L480 170 L510 170 L510 180
+ L540 180 L540 170 L570 170 L570 180 L600 180 L600 170 L630 170 L630 180
+ L650 180 L650 200 Z
+ " aria-hidden="true"/>
+
+ <!-- Left tower -->
+ <rect class="fill-wall-dark" x="130" y="140" width="60" height="240"/>
+ <path class="fill-wall-dark" d="M130 140 L130 120 L145 120 L145 110 L160 100 L175 110 L175 120 L190 120 L190 140 Z"/>
+ <!-- Left tower windows -->
+ <rect class="fill-window" x="150" y="160" width="12" height="18"/>
+ <rect class="fill-window" x="150" y="200" width="12" height="18"/>
+
+ <!-- Right tower -->
+ <rect class="fill-wall-dark" x="610" y="140" width="60" height="240"/>
+ <path class="fill-wall-dark" d="M610 140 L610 120 L625 120 L625 110 L640 100 L655 110 L655 120 L670 120 L670 140 Z"/>
+ <!-- Right tower windows -->
+ <rect class="fill-window" x="630" y="160" width="12" height="18"/>
+ <rect class="fill-window" x="630" y="200" width="12" height="18"/>
+
+ <!-- Wall detail bands -->
+ <rect class="fill-wall-dark" x="190" y="280" width="420" height="5" aria-hidden="true"/>
+ <rect class="fill-wall-light" x="190" y="250" width="420" height="3" aria-hidden="true"/>
+
+ <!-- === HOTSPOT: Grand Gate → Castle Interior === -->
+ <!-- Gate archway (decorative frame) -->
+ <g aria-hidden="true">
+ <path class="fill-wall-dark" d="
+ M355 380 L355 298
+ Q355 255 400 245
+ Q445 255 445 298
+ L445 380 Z
+ "/>
+ </g>
+ <!-- Gate door surface + link to interior -->
+ <a class="hotspot" href="pages/interior.html" aria-label="大门 — Enter the castle interior">
+ <title>大门 — Enter the castle interior</title>
+ <path class="hotspot-shape" d="
+ M362 380 L362 302
+ Q362 265 400 255
+ Q438 265 438 302
+ L438 380 Z
+ "/>
+ <!-- Gate door center line -->
+ <rect class="hotspot-icon" x="397" y="255" width="6" height="125"/>
+ <!-- Gate door handles -->
+ <circle class="fill-accent-dim" cx="390" cy="340" r="4"/>
+ <circle class="fill-accent-dim" cx="410" cy="340" r="4"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="400" y="242" text-anchor="middle">大门</text>
+ </a>
+
+ <!-- === HOTSPOT: Contact Phone === -->
+ <a class="hotspot" href="pages/contact.html" aria-label="联络处 — Contact">
+ <title>联络处 — Contact</title>
+ <rect class="hotspot-hitarea" x="215" y="276" width="100" height="100"/>
+ <!-- Phone hood/canopy (wider than body, protective overhang) -->
+ <rect class="hotspot-icon" x="247" y="304" width="36" height="5"/>
+ <!-- Phone body -->
+ <rect class="hotspot-shape" x="252" y="309" width="26" height="34"/>
+ <!-- Handset hanging on left side (cord implied) -->
+ <rect class="hotspot-icon" x="247" y="315" width="5" height="14"/>
+ <!-- Keypad area -->
+ <rect class="fill-accent-dim" x="258" y="315" width="14" height="10"/>
+ <!-- Coin slot -->
+ <rect class="fill-accent-dim" x="261" y="330" width="8" height="2"/>
+ <!-- Shelf (wider than body, resting surface) -->
+ <rect class="hotspot-icon" x="250" y="337" width="30" height="3"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="265" y="298" text-anchor="middle">联络处</text>
+ </a>
+
+ <!-- === HOTSPOT: Notice Board (Announcement) === -->
+ <a class="hotspot" href="pages/announcement.html" aria-label="领地公告 — Announcement">
+ <title>领地公告 — Announcement</title>
+ <rect class="hotspot-hitarea" x="493" y="298" width="100" height="100"/>
+ <!-- Board -->
+ <rect class="hotspot-shape" x="520" y="330" width="45" height="35"/>
+ <!-- Board post -->
+ <rect class="hotspot-icon" x="540" y="365" width="5" height="30"/>
+ <!-- Board text lines -->
+ <rect class="fill-accent-dim" x="527" y="338" width="31" height="3"/>
+ <rect class="fill-accent-dim" x="527" y="345" width="25" height="3"/>
+ <rect class="fill-accent-dim" x="527" y="352" width="28" height="3"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="543" y="323" text-anchor="middle">公告</text>
+ </a>
+
+ <!-- === HOTSPOT: Tombstone (Death / 遗言) === -->
+ <a class="hotspot" href="pages/death.html" aria-label="遗言 — Death">
+ <title>遗言 — Death</title>
+ <rect class="hotspot-hitarea" x="35" y="308" width="100" height="100"/>
+ <!-- Tombstone -->
+ <path class="hotspot-shape" d="
+ M70 380 L70 360
+ Q70 340 85 335
+ Q100 340 100 360
+ L100 380 Z
+ "/>
+ <!-- Ground mound -->
+ <path class="fill-ground" d="M60 380 Q85 370 110 380 Z"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="85" y="328" text-anchor="middle">遗言</text>
+ </a>
+
+ <!-- Trees (decorative) -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left tree cluster -->
+ <polygon class="fill-tree" points="30,340 50,280 70,340"/>
+ <polygon class="fill-tree" points="20,360 50,310 80,360"/>
+ <rect class="fill-tree" x="45" y="360" width="10" height="20"/>
+ <!-- Right tree -->
+ <polygon class="fill-tree" points="720,370 740,310 760,370"/>
+ <polygon class="fill-tree" points="710,390 740,340 770,390"/>
+ <rect class="fill-tree" x="735" y="390" width="10" height="20"/>
+ </g>
</svg>
- 侧门 — Contact
- </a>
- </nav>
- <!-- Divider -->
- <svg class="realm-divider" aria-hidden="true" focusable="false" style="margin-top:var(--space-xl)">
- <use href="#divider-battlement"/>
- </svg>
+ </div>
+
+ <nav id="scene-nav-exterior" class="scene-nav" aria-label="城堡外观导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="pages/interior.html">大门 — 城堡内部</a></li>
+ <li><a class="scene-nav__link" href="pages/contact.html">联络处 — 联系方式</a></li>
+ <li><a class="scene-nav__link" href="pages/announcement.html">公告 — 领地公告</a></li>
+ <li><a class="scene-nav__link" href="pages/death.html">遗言 — 墓志铭</a></li>
+ <li><a class="scene-nav__link" href="pages/neighbors.html">邻邦 — 离开城堡</a></li>
+ </ul>
+ </nav>
</main>
</body>
A pages/about.html => pages/about.html +213 -0
@@ 0,0 1,213 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>卧室 — Realm</title>
+ <meta name="description" content="卧室 — Bedroom of the realm lord">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-bedroom">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">卧室</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-bedroom-title" viewBox="0 0 800 500">
+ <title id="scene-bedroom-title">卧室 — An empty bedroom with moving boxes and a book on the floor</title>
+
+ <!-- ============================
+ 1. Background
+ ============================ -->
+ <rect class="fill-wall-dark" x="0" y="0" width="800" height="500"/>
+
+ <!-- ============================
+ 2. Merged ceiling + far wall
+ ============================ -->
+ <polygon class="fill-wall" points="0,0 800,0 720,50 720,370 80,370 80,50" aria-hidden="true"/>
+
+ <!-- ============================
+ 3. Far wall decorative lines
+ ============================ -->
+ <!-- Crown molding -->
+ <polygon class="fill-wall-light" points="80,50 720,50 720,56 80,56" aria-hidden="true"/>
+ <!-- Baseboard -->
+ <polygon class="fill-wall-dark" points="80,360 720,360 720,370 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 4. Left side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="0,0 80,50 80,370 0,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="80,50 72,54 72,366 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 5. Right side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="800,0 720,50 720,370 800,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="720,50 728,54 728,366 720,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 6. Ground floor + perspective tile lines
+ ============================ -->
+ <polygon class="fill-ground" points="80,370 720,370 800,500 0,500" aria-hidden="true"/>
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Horizontal lines -->
+ <polygon class="fill-path" points="80,370 720,370 718,372 82,372"/>
+ <polygon class="fill-path" points="56,400 744,400 743,402 57,402"/>
+ <polygon class="fill-path" points="30,430 770,430 769,432 31,432"/>
+ <polygon class="fill-path" points="0,460 800,460 800,462 0,462"/>
+ <!-- Converging vertical lines -->
+ <polygon class="fill-path" points="200,370 198,370 140,500 142,500"/>
+ <polygon class="fill-path" points="310,370 308,370 260,500 262,500"/>
+ <polygon class="fill-path" points="400,370 398,370 400,500 398,500"/>
+ <polygon class="fill-path" points="490,370 492,370 540,500 538,500"/>
+ <polygon class="fill-path" points="600,370 602,370 660,500 658,500"/>
+ </g>
+
+ <!-- ============================
+ 7. Window (far wall, right side, decorative)
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Window frame -->
+ <rect class="fill-wall-dark" x="560" y="120" width="100" height="140"/>
+ <!-- Window glass (semi-transparent orange glow) -->
+ <rect class="fill-window" x="568" y="128" width="84" height="124"/>
+ <!-- Window crossbar vertical -->
+ <rect class="fill-wall-dark" x="607" y="128" width="6" height="124"/>
+ <!-- Window crossbar horizontal -->
+ <rect class="fill-wall-dark" x="568" y="185" width="84" height="6"/>
+ <!-- Window sill -->
+ <rect class="fill-wall-light" x="555" y="260" width="110" height="8"/>
+ </g>
+
+ <!-- ============================
+ 8. Far wall boxes (background, smaller)
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Single box against far wall -->
+ <rect class="fill-wall" x="600" y="320" width="50" height="40"/>
+ <rect class="fill-wall-dark" x="600" y="320" width="50" height="5"/>
+ <!-- Tape -->
+ <rect class="fill-accent-dim" x="620" y="325" width="10" height="35"/>
+ </g>
+
+ <!-- ============================
+ 9. Left box stack (near left wall)
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Large box (on floor) -->
+ <rect class="fill-wall" x="110" y="310" width="80" height="60"/>
+ <rect class="fill-wall-dark" x="110" y="310" width="80" height="6"/>
+ <!-- Plank lines -->
+ <rect class="fill-wall-dark" x="110" y="340" width="80" height="2"/>
+ <!-- Tape -->
+ <rect class="fill-accent-dim" x="145" y="316" width="10" height="54"/>
+
+ <!-- Small box (stacked on large) -->
+ <rect class="fill-wall-dark" x="125" y="280" width="50" height="30"/>
+ <rect class="fill-wall" x="125" y="280" width="50" height="5"/>
+ <!-- Tape -->
+ <rect class="fill-accent-dim" x="145" y="285" width="10" height="25"/>
+ </g>
+
+ <!-- ============================
+ 10. Right box group (near right wall)
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Medium box (on floor) -->
+ <rect class="fill-wall" x="580" y="380" width="70" height="50"/>
+ <rect class="fill-wall-dark" x="580" y="380" width="70" height="5"/>
+ <!-- Tape -->
+ <rect class="fill-accent-dim" x="610" y="385" width="10" height="45"/>
+
+ <!-- Small box (beside, on floor) -->
+ <rect class="fill-wall-dark" x="660" y="400" width="40" height="25"/>
+ <rect class="fill-wall" x="660" y="400" width="40" height="4"/>
+ </g>
+
+ <!-- ============================
+ 11. Hotspot: Book (floor center)
+ ============================ -->
+ <a class="hotspot" href="#panel-book" aria-label="书 — Book about the realm lord">
+ <title>书 — 关于领主</title>
+ <rect class="hotspot-shape" x="355" y="400" width="90" height="40" rx="4"/>
+ <!-- Book cover (flat rectangle) -->
+ <rect class="fill-wall" x="365" y="410" width="70" height="10"/>
+ <!-- Book spine detail -->
+ <rect class="fill-accent-dim" x="368" y="412" width="64" height="2"/>
+ <rect class="fill-accent-dim" x="368" y="416" width="40" height="2"/>
+ <!-- Pages edge -->
+ <rect class="fill-wall-light" x="365" y="420" width="70" height="3"/>
+ <text class="hotspot-label" x="400" y="396" text-anchor="middle">书</text>
+ </a>
+
+ <!-- ============================
+ 12. Hotspot: Return to castle interior
+ ============================ -->
+ <a class="hotspot" href="interior.html" aria-label="返回城堡 — Return to castle interior">
+ <title>返回城堡 — Return to castle interior</title>
+ <rect class="hotspot-shape" x="350" y="450" width="100" height="45" rx="4"/>
+ <text class="hotspot-label" x="400" y="478" text-anchor="middle">返回城堡</text>
+ </a>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-bedroom" class="scene-nav" aria-label="卧室导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="#panel-book">书 — 关于领主</a></li>
+ <li><a class="scene-nav__link" href="interior.html">返回城堡</a></li>
+ </ul>
+ </nav>
+
+ <!-- ============================================================
+ capsule-panel: The open book
+ ============================================================ -->
+ <div id="panel-book" class="capsule-panel" tabindex="-1">
+ <div class="notice-board">
+ <div class="notice-board__frame">
+ <h2 class="notice-board__title">关于领主</h2>
+ <div class="notice-board__surface">
+ <h2>关于领主</h2>
+ <p>关于我的事情,要从何说起呢…… 卖关子。</p>
+ <p>人是分为现实和虚拟两个身份的。在虚拟的世界,或者说互联网上,我是这片领地的领主 Cytrogen——「领地」并不单单意味着该站。</p>
+ <p>不过我想,你会来到这里,是想要知道我现实中的身份吧。</p>
+
+ <h2>身世</h2>
+ <p>我是 00 后,山东人。大了后随着父母来到了纽约市居住,现在满打满算也至少在这里待了十多年了。</p>
+ <p>小时候就来了美国的人,几乎逃不开「身份问题」—— 到底是中国人还是美国人?我肯定是中国人没跑了,毕竟不是美国出生的,但对中国的很多地方也觉得陌生。较为直观的是,我的中文水平并没有那么好,让我很是惭愧。为了补足这一点,我会写博客文章,也会上中文课。</p>
+ <p>除了中文,我也在学习日语,说得并不好就是了…… 最初会学习日语,其实是为了和室友对话。</p>
+
+ <h2>创作</h2>
+ <p>我自童年时期开始,就喜欢画画和创作。不过种种原因让我没有继续这个爱好。结果,我的绘画水平大幅度降低…… 现在只能画些简单的小涂鸦和小动物。</p>
+
+ <h2>音乐</h2>
+ <p>音乐喜欢听 ボカロ、台湾摇滚和日语流行乐:</p>
+ <ul>
+ <li>最喜欢的 ボカロ P 主是 sasakure.UK</li>
+ <li>最喜欢的 ボカロ 歌曲是 《春嵐》</li>
+ <li>台湾摇滚中很难说喜欢谁……</li>
+ <li>但是日语流行乐我可以说我很中意 sakanaction</li>
+ </ul>
+ <p>我并不会唱歌,也不会弹奏任何乐器。</p>
+
+ <h2>游戏与硬件</h2>
+ <p>游戏方面,我喜欢玩沙盒、休闲、模拟经营游戏,例如《泰拉瑞亚》。我只会玩一款音乐游戏,也就是《舞萌 DX》。</p>
+ <p>我对硬件有一点兴趣,喜欢组装电脑,也喜欢跟着网上的视频组装一些小东西比如蓝牙音响,但是涉及的范围不广、反而非常狭隘。</p>
+
+ <h2>尾声</h2>
+ <p>我能说的关于自己的事情,也就这些了。我认为,想要了解一个人更多是从行动上观察来的,所以想要更多了解我的话,还请从我在网络上留下的痕迹中拼凑出一个大概的画像吧。</p>
+ </div>
+ </div>
+ </div>
+ <a href="#" class="capsule-panel__close">合上</a>
+ </div>
+
+ </main>
+
+</body>
+</html>
A pages/announcement.html => pages/announcement.html +43 -0
@@ 0,0 1,43 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>领地公告 — Realm</title>
+ <meta name="description" content="领地公告 — Realm announcement">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#main-content">跳至正文</a>
+
+ <main class="realm-scene" style="--scene-bg: oklch(0.10 0.02 290)">
+ <div class="realm-scene__content">
+ <div id="main-content" class="notice-board">
+ <div class="notice-board__frame">
+ <h1 class="notice-board__title">领地公告</h1>
+ <div class="notice-board__surface">
+ <h2><time datetime="2026-03-04">2026-03-04</time></h2>
+ <p>你现在所看到的领地,是它的第一个版本。</p>
+ <p>作为初版,难免会有不少粗糙之处——无论是显示上的问题、交互上的不便、还是内容上的疏漏,都有可能存在。如果你在探索途中发现了任何异常,希望能通过<a href="contact.html">联络处</a>告知于我,我会尽快修缮。</p>
+ <p>当然,若你对领地的建设有任何想法或建议,也欢迎一并告诉我。</p>
+ </div>
+ </div>
+ <div class="notice-board__post"></div>
+ <div class="notice-board__ground">
+ <svg aria-hidden="true" focusable="false" viewBox="0 0 400 60" preserveAspectRatio="none">
+ <rect class="fill-ground" x="0" y="20" width="400" height="40"/>
+ <path class="fill-ground" d="M140 20 Q200 0 260 20 Z"/>
+ </svg>
+ </div>
+ </div>
+ </div>
+
+ <nav class="realm-scene__nav realm-nav">
+ <a href="castle.html">← 返回领地</a>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/canon.html => pages/canon.html +327 -0
@@ 0,0 1,327 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>典籍室 — Realm</title>
+ <meta name="description" content="典籍室 — Canon and sources that nourish the Realm">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-canon">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">典籍室</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-canon-title" viewBox="0 0 800 500">
+ <title id="scene-canon-title">典籍室 — 古典书斋,内有书架、地图、留声机、棋盘与旅行日志</title>
+
+ <!-- ============================
+ 1. Background
+ ============================ -->
+ <rect class="fill-wall-dark" x="0" y="0" width="800" height="500"/>
+
+ <!-- ============================
+ 2. Far wall + ceiling
+ ============================ -->
+ <polygon class="fill-wall" points="0,0 800,0 720,50 720,370 80,370 80,50" aria-hidden="true"/>
+
+ <!-- ============================
+ 3. Far wall decorative lines
+ ============================ -->
+ <!-- Crown molding -->
+ <polygon class="fill-wall-light" points="80,50 720,50 720,56 80,56" aria-hidden="true"/>
+ <!-- Baseboard -->
+ <polygon class="fill-wall-dark" points="80,360 720,360 720,370 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 4. Left side wall + highlight
+ ============================ -->
+ <polygon class="fill-wall-dark" points="0,0 80,50 80,370 0,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="80,50 72,54 72,366 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 5. Right side wall + highlight
+ ============================ -->
+ <polygon class="fill-wall-dark" points="800,0 720,50 720,370 800,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="720,50 728,54 728,366 720,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 6. Ground + perspective grid
+ ============================ -->
+ <polygon class="fill-ground" points="80,370 720,370 800,500 0,500" aria-hidden="true"/>
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Horizontal lines -->
+ <polygon class="fill-path" points="80,370 720,370 718,372 82,372"/>
+ <polygon class="fill-path" points="56,400 744,400 743,402 57,402"/>
+ <polygon class="fill-path" points="30,430 770,430 769,432 31,432"/>
+ <polygon class="fill-path" points="0,460 800,460 800,462 0,462"/>
+ <!-- Converging vertical lines -->
+ <polygon class="fill-path" points="200,370 198,370 140,500 142,500"/>
+ <polygon class="fill-path" points="310,370 308,370 260,500 262,500"/>
+ <polygon class="fill-path" points="400,370 398,370 400,500 398,500"/>
+ <polygon class="fill-path" points="490,370 492,370 540,500 538,500"/>
+ <polygon class="fill-path" points="600,370 602,370 660,500 658,500"/>
+ </g>
+
+ <!-- ============================
+ 7. Scene title plaque (far wall upper center)
+ ============================ -->
+ <g aria-hidden="true">
+ <rect class="fill-wall-dark" x="280" y="64" width="240" height="24" rx="2"/>
+ <rect class="fill-wall-light" x="284" y="67" width="232" height="18" rx="1"/>
+ </g>
+ <text class="scene-title" x="400" y="81" text-anchor="middle">此处记载着滋养这片领地的源头</text>
+
+ <!-- ============================
+ 8. Torches (decorative)
+ ============================ -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left wall torch -->
+ <rect class="fill-wall-light" x="80" y="260" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="78" y="252" width="10" height="10"/>
+ <rect class="fill-window-glow" x="73" y="244" width="20" height="12"/>
+ <!-- Right wall torch -->
+ <rect class="fill-wall-light" x="714" y="260" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="712" y="252" width="10" height="10"/>
+ <rect class="fill-window-glow" x="707" y="244" width="20" height="12"/>
+ </g>
+
+ <!-- ============================
+ 9. Reading table (decorative, center ground)
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Table top -->
+ <rect class="fill-wall" x="340" y="378" width="90" height="8" rx="2"/>
+ <!-- Table legs -->
+ <rect class="fill-wall-dark" x="350" y="386" width="6" height="38"/>
+ <rect class="fill-wall-dark" x="414" y="386" width="6" height="38"/>
+ <!-- Open book on table -->
+ <polygon class="fill-door" points="358,370 383,374 383,378 358,378"/>
+ <polygon class="fill-wall-light" points="383,374 408,370 408,378 383,378"/>
+ </g>
+
+ <!-- ============================
+ 10. HOTSPOT: Bookshelf 书架 (far wall left) → panel-books
+ ============================ -->
+ <a class="hotspot" href="#panel-books" aria-label="书架 — 书籍">
+ <title>书架 — Books</title>
+ <!-- Bookcase frame -->
+ <rect class="hotspot-shape" x="110" y="95" width="130" height="265" rx="3"/>
+ <!-- Shelves -->
+ <rect class="fill-wall-dark" x="118" y="150" width="114" height="4"/>
+ <rect class="fill-wall-dark" x="118" y="208" width="114" height="4"/>
+ <rect class="fill-wall-dark" x="118" y="266" width="114" height="4"/>
+ <rect class="fill-wall-dark" x="118" y="324" width="114" height="4"/>
+ <!-- Books row 1 -->
+ <rect class="fill-accent-dim" x="122" y="102" width="12" height="46"/>
+ <rect class="fill-window" x="138" y="108" width="10" height="40"/>
+ <rect class="fill-accent-shape" x="152" y="104" width="14" height="44"/>
+ <rect class="fill-wall-light" x="170" y="110" width="10" height="38"/>
+ <rect class="fill-door" x="184" y="102" width="12" height="46"/>
+ <rect class="fill-window" x="200" y="106" width="11" height="42"/>
+ <rect class="fill-accent-dim" x="215" y="104" width="12" height="44"/>
+ <!-- Books row 2 -->
+ <rect class="fill-door" x="122" y="158" width="14" height="48"/>
+ <rect class="fill-accent-dim" x="140" y="162" width="10" height="44"/>
+ <rect class="fill-window" x="154" y="156" width="12" height="50"/>
+ <rect class="fill-wall-light" x="170" y="160" width="10" height="46"/>
+ <rect class="fill-accent-shape" x="184" y="158" width="14" height="48"/>
+ <rect class="fill-door" x="202" y="164" width="10" height="42"/>
+ <rect class="fill-window" x="216" y="156" width="12" height="50"/>
+ <!-- Books row 3 -->
+ <rect class="fill-accent-shape" x="122" y="216" width="12" height="48"/>
+ <rect class="fill-door" x="138" y="220" width="10" height="44"/>
+ <rect class="fill-accent-dim" x="152" y="214" width="14" height="50"/>
+ <rect class="fill-window" x="170" y="218" width="10" height="46"/>
+ <rect class="fill-wall-light" x="184" y="216" width="12" height="48"/>
+ <rect class="fill-accent-dim" x="200" y="222" width="10" height="42"/>
+ <rect class="fill-door" x="214" y="214" width="14" height="50"/>
+ <!-- Books row 4 -->
+ <rect class="fill-window" x="122" y="274" width="14" height="48"/>
+ <rect class="fill-accent-shape" x="140" y="278" width="10" height="44"/>
+ <rect class="fill-door" x="154" y="272" width="12" height="50"/>
+ <rect class="fill-wall-light" x="170" y="276" width="10" height="46"/>
+ <rect class="fill-accent-dim" x="184" y="274" width="14" height="48"/>
+ <rect class="fill-window" x="202" y="280" width="10" height="42"/>
+ <rect class="fill-accent-shape" x="216" y="272" width="12" height="50"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="175" y="87" text-anchor="middle">书架</text>
+ </a>
+
+ <!-- ============================
+ 11. HOTSPOT: Map 地图 (left wall) → panel-places
+ ============================ -->
+ <a class="hotspot" href="#panel-places" aria-label="地图 — 地点">
+ <title>地图 — Places</title>
+ <!-- Map frame on left wall (perspective-adjusted) -->
+ <polygon class="hotspot-shape" points="24,140 72,148 72,296 24,308"/>
+ <!-- Map surface -->
+ <polygon class="fill-door" points="30,148 68,155 68,289 30,300"/>
+ <!-- Map markers -->
+ <rect class="fill-accent-shape" x="40" y="180" width="6" height="6"/>
+ <rect class="fill-accent-shape" x="52" y="220" width="6" height="6"/>
+ <rect class="fill-accent-dim" x="36" y="252" width="6" height="6"/>
+ <rect class="fill-window" x="54" y="196" width="5" height="5"/>
+ <rect class="fill-window-glow" x="42" y="270" width="5" height="5"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="48" y="130" text-anchor="middle">地图</text>
+ </a>
+
+ <!-- ============================
+ 12. HOTSPOT: Gramophone 留声机 (far wall right) → shelf-media (locked)
+ ============================ -->
+ <g id="shelf-media">
+ <a class="hotspot" href="#shelf-media" aria-label="视听 — 尚未记载">
+ <title>视听 — 尚未记载</title>
+ <!-- Cabinet/stand -->
+ <rect class="hotspot-shape" x="560" y="260" width="100" height="100" rx="3"/>
+ <!-- Cabinet front detail -->
+ <rect class="fill-wall-light" x="568" y="270" width="84" height="80"/>
+ <!-- Gramophone base plate -->
+ <rect class="fill-door" x="578" y="248" width="64" height="14"/>
+ <!-- Turntable -->
+ <circle class="fill-wall-dark" cx="610" cy="236" r="20"/>
+ <circle class="fill-door" cx="610" cy="236" r="8"/>
+ <circle class="fill-accent-dim" cx="610" cy="236" r="3"/>
+ <!-- Horn -->
+ <polygon class="fill-accent-dim" points="626,228 660,195 660,212 630,236"/>
+ <!-- Horn mouth -->
+ <rect class="fill-accent-shape" x="656" y="192" width="8" height="22" rx="2"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="610" y="183" text-anchor="middle">视听</text>
+ </a>
+ <g class="capsule-lock" aria-hidden="true">
+ <path class="fill-wall-light" d="M606 300 L606 292 Q606 284 610 284 Q614 284 614 292 L614 300"/>
+ <rect class="fill-wall" x="602" y="300" width="16" height="12" rx="2"/>
+ <circle class="fill-door" cx="610" cy="306" r="2"/>
+ </g>
+ <text class="capsule-lock-text" x="610" y="175" text-anchor="middle">尚未记载</text>
+ </g>
+
+ <!-- ============================
+ 13. HOTSPOT: Chess table 棋盘台 (ground right) → shelf-games (locked)
+ ============================ -->
+ <g id="shelf-games">
+ <a class="hotspot" href="#shelf-games" aria-label="游戏 — 尚未记载">
+ <title>游戏 — 尚未记载</title>
+ <!-- Table top -->
+ <rect class="hotspot-shape" x="530" y="378" width="100" height="10" rx="2"/>
+ <!-- Table legs -->
+ <rect class="hotspot-shape" x="538" y="388" width="8" height="42"/>
+ <rect class="hotspot-shape" x="614" y="388" width="8" height="42"/>
+ <!-- Board on table -->
+ <rect class="fill-wall-light" x="545" y="370" width="70" height="8"/>
+ <!-- Grid lines on board -->
+ <rect class="fill-wall-dark" x="562" y="370" width="1" height="8"/>
+ <rect class="fill-wall-dark" x="580" y="370" width="1" height="8"/>
+ <rect class="fill-wall-dark" x="597" y="370" width="1" height="8"/>
+ <rect class="fill-wall-dark" x="545" y="374" width="70" height="1"/>
+ <!-- Pieces -->
+ <rect class="fill-accent-dim" x="550" y="366" width="6" height="4"/>
+ <rect class="fill-door" x="568" y="366" width="6" height="4"/>
+ <rect class="fill-accent-dim" x="585" y="366" width="6" height="4"/>
+ <rect class="fill-door" x="602" y="366" width="6" height="4"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="580" y="358" text-anchor="middle">游戏</text>
+ </a>
+ <g class="capsule-lock" aria-hidden="true">
+ <path class="fill-wall-light" d="M576 394 L576 386 Q576 378 580 378 Q584 378 584 386 L584 394"/>
+ <rect class="fill-wall" x="572" y="394" width="16" height="12" rx="2"/>
+ <circle class="fill-door" cx="580" cy="400" r="2"/>
+ </g>
+ <text class="capsule-lock-text" x="580" y="350" text-anchor="middle">尚未记载</text>
+ </g>
+
+ <!-- ============================
+ 14. HOTSPOT: Travel journal 旅行记 (right wall) → shelf-experiences (locked)
+ ============================ -->
+ <g id="shelf-experiences">
+ <a class="hotspot" href="#shelf-experiences" aria-label="经历 — 尚未记载">
+ <title>经历 — 尚未记载</title>
+ <!-- Journal frame on right wall (perspective-adjusted) -->
+ <polygon class="hotspot-shape" points="728,148 776,140 776,308 728,296"/>
+ <!-- Journal pages -->
+ <polygon class="fill-door" points="732,155 772,148 772,300 732,289"/>
+ <!-- Page lines (writing) -->
+ <rect class="fill-wall-dark" x="738" y="168" width="28" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="180" width="26" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="192" width="30" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="204" width="24" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="224" width="28" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="236" width="26" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="248" width="30" height="2"/>
+ <rect class="fill-wall-dark" x="738" y="260" width="22" height="2"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="752" y="130" text-anchor="middle">经历</text>
+ </a>
+ <g class="capsule-lock" aria-hidden="true">
+ <path class="fill-wall-light" d="M749 228 L749 220 Q749 212 753 212 Q757 212 757 220 L757 228"/>
+ <rect class="fill-wall" x="745" y="228" width="16" height="12" rx="2"/>
+ <circle class="fill-door" cx="753" cy="234" r="2"/>
+ </g>
+ <text class="capsule-lock-text" x="752" y="122" text-anchor="middle">尚未记载</text>
+ </g>
+
+ <!-- ============================
+ 15. HOTSPOT: Return door 返回城堡 (ground bottom center)
+ ============================ -->
+ <a class="hotspot" href="interior.html" aria-label="返回城堡 — Return to castle interior">
+ <title>返回城堡 — Return to castle interior</title>
+ <rect class="hotspot-shape" x="350" y="450" width="100" height="45" rx="4"/>
+ <text class="hotspot-label" x="400" y="478" text-anchor="middle">返回城堡</text>
+ </a>
+ </svg>
+
+ </div>
+
+ <!-- :target overlay panels -->
+
+ <nav id="scene-nav-canon" class="scene-nav" aria-label="典籍室导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="#panel-books">书架 — 书籍</a></li>
+ <li><a class="scene-nav__link" href="#panel-places">地图 — 地点</a></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">视听(尚未记载)</span></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">游戏(尚未记载)</span></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">经历(尚未记载)</span></li>
+ <li><a class="scene-nav__link" href="interior.html">返回城堡</a></li>
+ </ul>
+ </nav>
+
+ <div id="panel-books" class="capsule-panel" tabindex="-1">
+ <div class="scroll">
+ <div class="scroll__rod" aria-hidden="true"></div>
+ <div class="scroll__body">
+ <h1 class="scroll__title">书籍</h1>
+ <h2>《不原谅也没关系》</h2>
+ <p>这本书改变了我看人的角度。通常来说,将人视为天生且不会改变的是很便利的做法。实际上,许多被我们归结为固有性格特质的行为是个体在长期创伤环境中形成的防御机制,也就是所谓的 4F 反应。我理解到,他人的许多地方都可以通过他们所处的环境来推测出来。借此,我暗自分析了身边的许多人,也了解了他们许多。站在这种角度去看,会发现自己能够理解原先不可理喻的蠢人或者坏人们。但这也不意味着我需要无底线包容他们的越界行为。</p>
+ <p>不过,我对这种概念还在缓慢消化中。生气的时候还是会偷偷将对方视为「一辈子的恶人」来数落。</p>
+ </div>
+ <div class="scroll__rod" aria-hidden="true"></div>
+ </div>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <div id="panel-places" class="capsule-panel" tabindex="-1">
+ <div class="scroll">
+ <div class="scroll__rod" aria-hidden="true"></div>
+ <div class="scroll__body">
+ <h1 class="scroll__title">地点</h1>
+ <p>我是南北家庭出身,但是在北方(山东)居住的时间更长久,也更融入到当地的文化中。因为小时候在福建的生活并不快乐,所以我对那个地方带有一些自己的小偏见。</p>
+ <p>在中国生活了十一年后,我随着父母搬来纽约定居。无论是新生活带来的压力和恐惧、同父母之间每日每夜的争执,还是日后难以融入当地的人群中,都让我倍受折磨,也构成了我青少年时期的底色。上高中时,我已然是一个对社交感到恐惧且自负的人,这也导致了未来一系列糟糕的事情。</p>
+ <p>尽管在高中期间我离开了家,不再需要每天和父母产生摩擦,但也让我陷入了另一个泥潭,也就是和室友之间的爱恨情仇。我们之间发生了很多,也改变了彼此很多。毫无疑问的是,我们互相是对方最亲密的人,至今也是。</p>
+ <p>在美国的这十几年,我从未回到中国去,导致我对中国的认知严重脱节。不过也正因此,你会在本站看到更多与美国境内相关的内容。</p>
+ </div>
+ <div class="scroll__rod" aria-hidden="true"></div>
+ </div>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ </main>
+
+</body>
+</html>
A pages/castle.html => pages/castle.html +201 -0
@@ 0,0 1,201 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Realm — cytrogen.icu</title>
+ <meta name="description" content="Realm — the visual exploration territory of cytrogen.icu">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-exterior">跳过场景</a>
+
+ <!-- ============================================================
+ Main Folder Layout
+ ============================================================ -->
+ <main class="realm-folder">
+ <h1 class="visually-hidden">城堡外观</h1>
+
+ <!-- Folder Content -->
+ <div class="folder-content">
+
+ <!-- ======================================================
+ Castle Exterior (城堡外观)
+ ====================================================== -->
+ <svg role="group" aria-labelledby="scene-exterior-title" viewBox="0 0 800 500">
+ <title id="scene-exterior-title">城堡外观 — Castle exterior scene with gate, contact phone, notice board, and grave</title>
+
+ <!-- Sky -->
+ <rect class="fill-sky" x="0" y="0" width="800" height="500"/>
+
+ <!-- Stars (decorative detail) -->
+ <g class="scene-detail" aria-hidden="true">
+ <rect class="fill-star" x="80" y="30" width="3" height="3"/>
+ <rect class="fill-star" x="200" y="55" width="2" height="2"/>
+ <rect class="fill-star" x="350" y="20" width="3" height="3"/>
+ <rect class="fill-star" x="520" y="45" width="2" height="2"/>
+ <rect class="fill-star" x="680" y="25" width="3" height="3"/>
+ <rect class="fill-star" x="740" y="60" width="2" height="2"/>
+ <rect class="fill-star" x="150" y="80" width="2" height="2"/>
+ <rect class="fill-star" x="600" y="70" width="2" height="2"/>
+ </g>
+
+ <!-- Moon -->
+ <circle class="fill-moon" cx="680" cy="80" r="30" aria-hidden="true"/>
+ <circle class="fill-sky" cx="695" cy="70" r="28" aria-hidden="true"/>
+
+ <!-- Distant mountains -->
+ <path class="fill-mountain-far" d="M0 280 L100 180 L200 240 L320 160 L440 220 L540 170 L650 230 L750 190 L800 220 L800 320 L0 320 Z" aria-hidden="true"/>
+ <path class="fill-mountain" d="M0 310 L80 250 L180 290 L280 230 L380 270 L500 220 L600 280 L700 250 L800 290 L800 340 L0 340 Z" aria-hidden="true"/>
+
+ <!-- Ground -->
+ <rect class="fill-ground" x="0" y="330" width="800" height="170"/>
+
+ <!-- === HOTSPOT: Road → Neighboring Lands === -->
+ <a class="hotspot" href="neighbors.html" aria-label="邻邦 — Neighboring lands">
+ <title>邻邦 — Neighboring lands</title>
+ <path class="hotspot-shape fill-path" d="M350 500 L450 500 L438 380 L362 380 Z"/>
+ <text class="hotspot-label" x="400" y="470" text-anchor="middle">走</text>
+ </a>
+
+ <!-- Castle main wall -->
+ <rect class="fill-wall" x="150" y="200" width="500" height="180"/>
+
+ <!-- Castle battlements -->
+ <path class="fill-wall" d="
+ M150 200 L150 180 L180 180 L180 170 L210 170 L210 180 L240 180 L240 170 L270 170 L270 180
+ L300 180 L300 170 L330 170 L330 180 L360 180 L360 170 L390 170 L390 180
+ L420 180 L420 170 L450 170 L450 180 L480 180 L480 170 L510 170 L510 180
+ L540 180 L540 170 L570 170 L570 180 L600 180 L600 170 L630 170 L630 180
+ L650 180 L650 200 Z
+ " aria-hidden="true"/>
+
+ <!-- Left tower -->
+ <rect class="fill-wall-dark" x="130" y="140" width="60" height="240"/>
+ <path class="fill-wall-dark" d="M130 140 L130 120 L145 120 L145 110 L160 100 L175 110 L175 120 L190 120 L190 140 Z"/>
+ <!-- Left tower windows -->
+ <rect class="fill-window" x="150" y="160" width="12" height="18"/>
+ <rect class="fill-window" x="150" y="200" width="12" height="18"/>
+
+ <!-- Right tower -->
+ <rect class="fill-wall-dark" x="610" y="140" width="60" height="240"/>
+ <path class="fill-wall-dark" d="M610 140 L610 120 L625 120 L625 110 L640 100 L655 110 L655 120 L670 120 L670 140 Z"/>
+ <!-- Right tower windows -->
+ <rect class="fill-window" x="630" y="160" width="12" height="18"/>
+ <rect class="fill-window" x="630" y="200" width="12" height="18"/>
+
+ <!-- Wall detail bands -->
+ <rect class="fill-wall-dark" x="190" y="280" width="420" height="5" aria-hidden="true"/>
+ <rect class="fill-wall-light" x="190" y="250" width="420" height="3" aria-hidden="true"/>
+
+ <!-- === HOTSPOT: Grand Gate → Castle Interior === -->
+ <!-- Gate archway (decorative frame) -->
+ <g aria-hidden="true">
+ <path class="fill-wall-dark" d="
+ M355 380 L355 298
+ Q355 255 400 245
+ Q445 255 445 298
+ L445 380 Z
+ "/>
+ </g>
+ <!-- Gate door surface + link to interior -->
+ <a class="hotspot" href="interior.html" aria-label="大门 — Enter the castle interior">
+ <title>大门 — Enter the castle interior</title>
+ <path class="hotspot-shape" d="
+ M362 380 L362 302
+ Q362 265 400 255
+ Q438 265 438 302
+ L438 380 Z
+ "/>
+ <!-- Gate door center line -->
+ <rect class="hotspot-icon" x="397" y="255" width="6" height="125"/>
+ <!-- Gate door handles -->
+ <circle class="fill-accent-dim" cx="390" cy="340" r="4"/>
+ <circle class="fill-accent-dim" cx="410" cy="340" r="4"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="400" y="242" text-anchor="middle">大门</text>
+ </a>
+
+ <!-- === HOTSPOT: Contact Phone === -->
+ <a class="hotspot" href="contact.html" aria-label="联络处 — Contact">
+ <title>联络处 — Contact</title>
+ <rect class="hotspot-hitarea" x="215" y="276" width="100" height="100"/>
+ <!-- Phone hood/canopy (wider than body, protective overhang) -->
+ <rect class="hotspot-icon" x="247" y="304" width="36" height="5"/>
+ <!-- Phone body -->
+ <rect class="hotspot-shape" x="252" y="309" width="26" height="34"/>
+ <!-- Handset hanging on left side (cord implied) -->
+ <rect class="hotspot-icon" x="247" y="315" width="5" height="14"/>
+ <!-- Keypad area -->
+ <rect class="fill-accent-dim" x="258" y="315" width="14" height="10"/>
+ <!-- Coin slot -->
+ <rect class="fill-accent-dim" x="261" y="330" width="8" height="2"/>
+ <!-- Shelf (wider than body, resting surface) -->
+ <rect class="hotspot-icon" x="250" y="337" width="30" height="3"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="265" y="298" text-anchor="middle">联络处</text>
+ </a>
+
+ <!-- === HOTSPOT: Notice Board (Announcement) === -->
+ <a class="hotspot" href="announcement.html" aria-label="领地公告 — Announcement">
+ <title>领地公告 — Announcement</title>
+ <rect class="hotspot-hitarea" x="493" y="298" width="100" height="100"/>
+ <!-- Board -->
+ <rect class="hotspot-shape" x="520" y="330" width="45" height="35"/>
+ <!-- Board post -->
+ <rect class="hotspot-icon" x="540" y="365" width="5" height="30"/>
+ <!-- Board text lines -->
+ <rect class="fill-accent-dim" x="527" y="338" width="31" height="3"/>
+ <rect class="fill-accent-dim" x="527" y="345" width="25" height="3"/>
+ <rect class="fill-accent-dim" x="527" y="352" width="28" height="3"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="543" y="323" text-anchor="middle">公告</text>
+ </a>
+
+ <!-- === HOTSPOT: Tombstone (Death / 遗言) === -->
+ <a class="hotspot" href="death.html" aria-label="遗言 — Death">
+ <title>遗言 — Death</title>
+ <rect class="hotspot-hitarea" x="35" y="308" width="100" height="100"/>
+ <!-- Tombstone -->
+ <path class="hotspot-shape" d="
+ M70 380 L70 360
+ Q70 340 85 335
+ Q100 340 100 360
+ L100 380 Z
+ "/>
+ <!-- Ground mound -->
+ <path class="fill-ground" d="M60 380 Q85 370 110 380 Z"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="85" y="328" text-anchor="middle">遗言</text>
+ </a>
+
+ <!-- Trees (decorative) -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left tree cluster -->
+ <polygon class="fill-tree" points="30,340 50,280 70,340"/>
+ <polygon class="fill-tree" points="20,360 50,310 80,360"/>
+ <rect class="fill-tree" x="45" y="360" width="10" height="20"/>
+ <!-- Right tree -->
+ <polygon class="fill-tree" points="720,370 740,310 760,370"/>
+ <polygon class="fill-tree" points="710,390 740,340 770,390"/>
+ <rect class="fill-tree" x="735" y="390" width="10" height="20"/>
+ </g>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-exterior" class="scene-nav" aria-label="城堡外观导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="interior.html">大门 — 城堡内部</a></li>
+ <li><a class="scene-nav__link" href="contact.html">联络处 — 联系方式</a></li>
+ <li><a class="scene-nav__link" href="announcement.html">公告 — 领地公告</a></li>
+ <li><a class="scene-nav__link" href="death.html">遗言 — 墓志铭</a></li>
+ <li><a class="scene-nav__link" href="neighbors.html">邻邦 — 离开城堡</a></li>
+ </ul>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/colophon.html => pages/colophon.html +748 -0
@@ 0,0 1,748 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>工坊 — Realm</title>
+ <meta name="description" content="工坊 — Colophon, how this realm was built">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-workshop">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">工坊</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-workshop-title" viewBox="0 0 800 500">
+ <title id="scene-workshop-title">工坊 — Workshop interior with forge, workbench, tool rack, and blueprints</title>
+
+ <!-- ============================
+ 1. Background
+ ============================ -->
+ <rect class="fill-wall-dark" x="0" y="0" width="800" height="500"/>
+
+ <!-- ============================
+ 2. Merged ceiling + far wall
+ ============================ -->
+ <polygon class="fill-wall" points="0,0 800,0 720,50 720,370 80,370 80,50" aria-hidden="true"/>
+
+ <!-- ============================
+ 3. Far wall decorative lines
+ ============================ -->
+ <!-- Crown molding -->
+ <polygon class="fill-wall-light" points="80,50 720,50 720,56 80,56" aria-hidden="true"/>
+ <!-- Baseboard -->
+ <polygon class="fill-wall-dark" points="80,360 720,360 720,370 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 4. Left side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="0,0 80,50 80,370 0,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="80,50 72,54 72,366 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 5. Right side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="800,0 720,50 720,370 800,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="720,50 728,54 728,366 720,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 6. Ground floor + perspective tile lines
+ ============================ -->
+ <polygon class="fill-ground" points="80,370 720,370 800,500 0,500" aria-hidden="true"/>
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Horizontal lines -->
+ <polygon class="fill-path" points="80,370 720,370 718,372 82,372"/>
+ <polygon class="fill-path" points="56,400 744,400 743,402 57,402"/>
+ <polygon class="fill-path" points="30,430 770,430 769,432 31,432"/>
+ <polygon class="fill-path" points="0,460 800,460 800,462 0,462"/>
+ <!-- Converging vertical lines -->
+ <polygon class="fill-path" points="200,370 198,370 140,500 142,500"/>
+ <polygon class="fill-path" points="310,370 308,370 260,500 262,500"/>
+ <polygon class="fill-path" points="400,370 398,370 400,500 398,500"/>
+ <polygon class="fill-path" points="490,370 492,370 540,500 538,500"/>
+ <polygon class="fill-path" points="600,370 602,370 660,500 658,500"/>
+ </g>
+
+ <!-- ============================
+ 7. Chimney / hood (decorative)
+ Extends from far wall ceiling down to forge
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Narrow stack near ceiling -->
+ <rect class="fill-wall-dark" x="500" y="56" width="20" height="100"/>
+ <!-- Widening section toward forge -->
+ <polygon class="fill-wall-dark" points="500,156 520,156 540,262 480,262"/>
+ <!-- Hood face -->
+ <rect class="fill-wall" x="478" y="256" width="64" height="8"/>
+ </g>
+
+ <!-- ============================
+ 8. Hotspot: Tool rack 工具 (far wall left)
+ ============================ -->
+ <a class="hotspot" href="#panel-tools" aria-label="工具 — Tools">
+ <title>工具 — Tools</title>
+ <rect class="hotspot-shape" x="118" y="78" width="100" height="125"/>
+ <!-- Backboard -->
+ <rect class="fill-wall-dark" x="122" y="82" width="92" height="117"/>
+ <!-- Top shelf -->
+ <rect class="fill-wall-light" x="118" y="100" width="100" height="6"/>
+ <!-- Middle shelf -->
+ <rect class="fill-wall-light" x="118" y="140" width="100" height="6"/>
+ <!-- Bottom shelf -->
+ <rect class="fill-wall-light" x="118" y="180" width="100" height="6"/>
+ <!-- Tool silhouettes: hammer -->
+ <rect class="fill-door" x="132" y="108" width="4" height="28"/>
+ <rect class="fill-door" x="128" y="108" width="12" height="6"/>
+ <!-- Tool silhouettes: tongs -->
+ <rect class="fill-door" x="157" y="108" width="3" height="26"/>
+ <rect class="fill-door" x="164" y="108" width="3" height="26"/>
+ <!-- Tool silhouettes: file -->
+ <rect class="fill-door" x="187" y="108" width="4" height="28"/>
+ <!-- Items on middle shelf -->
+ <rect class="fill-door" x="130" y="148" width="18" height="6"/>
+ <rect class="fill-door" x="160" y="148" width="12" height="8"/>
+ <rect class="fill-door" x="186" y="148" width="16" height="5"/>
+ <text class="hotspot-label" x="168" y="72" text-anchor="middle">工具</text>
+ </a>
+
+ <!-- ============================
+ 9. Hotspot: Blueprint 蓝图 (far wall right)
+ ============================ -->
+ <a class="hotspot" href="#panel-blueprint" aria-label="蓝图 — Blueprint">
+ <title>蓝图 — Blueprint</title>
+ <rect class="hotspot-shape" x="578" y="83" width="115" height="115"/>
+ <!-- Parchment -->
+ <rect class="fill-board" x="585" y="90" width="100" height="100"/>
+ <!-- Pin at top center -->
+ <circle class="fill-accent-shape" cx="635" cy="90" r="4"/>
+ <!-- Schematic lines -->
+ <rect class="fill-path" x="595" y="110" width="80" height="2"/>
+ <rect class="fill-path" x="595" y="125" width="60" height="2"/>
+ <rect class="fill-path" x="595" y="140" width="70" height="2"/>
+ <rect class="fill-path" x="595" y="155" width="50" height="2"/>
+ <rect class="fill-path" x="595" y="170" width="80" height="2"/>
+ <!-- Small floor plan rectangle -->
+ <rect class="fill-path" x="640" y="118" width="30" height="40"/>
+ <rect class="fill-board" x="645" y="123" width="20" height="30"/>
+ <text class="hotspot-label" x="635" y="77" text-anchor="middle">蓝图</text>
+ </a>
+
+ <!-- ============================
+ 10. Torch sconces (decorative)
+ ============================ -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left side wall torch -->
+ <rect class="fill-wall-light" x="82" y="250" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="80" y="242" width="10" height="10"/>
+ <rect class="fill-window-glow" x="75" y="234" width="20" height="12"/>
+ <!-- Right side wall torch -->
+ <rect class="fill-wall-light" x="712" y="250" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="710" y="242" width="10" height="10"/>
+ <rect class="fill-window-glow" x="705" y="234" width="20" height="12"/>
+ </g>
+
+ <!-- ============================
+ 11. Hotspot: Forge 锻造 (centerpiece)
+ ============================ -->
+ <a class="hotspot" href="#panel-forging" aria-label="锻造 — Forging">
+ <title>锻造 — Forging</title>
+ <!-- Clickable area -->
+ <rect class="hotspot-shape" x="430" y="250" width="180" height="120"/>
+ <!-- Stone body -->
+ <rect class="fill-wall" x="445" y="280" width="150" height="90"/>
+ <!-- Left pillar -->
+ <rect class="fill-wall-dark" x="432" y="268" width="18" height="102"/>
+ <!-- Right pillar -->
+ <rect class="fill-wall-dark" x="590" y="268" width="18" height="102"/>
+ <!-- Hearth ledge -->
+ <rect class="fill-wall-light" x="430" y="268" width="180" height="14"/>
+ <!-- Stone texture lines -->
+ <rect class="fill-path" x="450" y="312" width="140" height="2"/>
+ <rect class="fill-path" x="450" y="342" width="140" height="2"/>
+ <!-- Fire opening (black recess) -->
+ <rect class="fill-door" x="462" y="296" width="116" height="60"/>
+ <!-- Ambient glow halo (pulsing) -->
+ <rect class="fill-window-glow forge-glow" x="455" y="288" width="130" height="72"/>
+ <!-- Fire body (semi-transparent orange) -->
+ <rect class="fill-window" x="472" y="310" width="96" height="38"/>
+ <!-- Coals (solid orange) -->
+ <rect class="fill-accent-shape" x="478" y="336" width="84" height="18"/>
+ <!-- Fire tongues -->
+ <rect class="fill-accent-shape" x="496" y="318" width="12" height="18"/>
+ <rect class="fill-accent-shape" x="519" y="322" width="10" height="14"/>
+ <rect class="fill-accent-shape" x="541" y="320" width="8" height="16"/>
+ <!-- Front hearth base -->
+ <rect class="fill-wall-dark" x="430" y="360" width="180" height="10"/>
+ <text class="hotspot-label" x="520" y="258" text-anchor="middle">锻造</text>
+ </a>
+
+ <!-- ============================
+ 12. Anvil (decorative, near forge)
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Base (wider) -->
+ <polygon class="fill-wall" points="352,370 398,370 392,355 358,355"/>
+ <!-- Waist (narrow) -->
+ <rect class="fill-wall" x="365" y="345" width="20" height="10"/>
+ <!-- Top face (trapezoidal) -->
+ <polygon class="fill-wall-light" points="348,345 402,345 395,330 355,330"/>
+ <!-- Horn (left extension) -->
+ <polygon class="fill-wall-light" points="348,345 355,330 338,336"/>
+ <!-- Hot metal piece -->
+ <rect class="fill-accent-shape" x="368" y="326" width="20" height="5"/>
+ </g>
+
+ <!-- ============================
+ 13. Hotspot: Workbench 技法 (floor left)
+ ============================ -->
+ <a class="hotspot" href="#panel-techniques" aria-label="技法 — Techniques">
+ <title>技法 — Techniques</title>
+ <rect class="hotspot-shape" x="100" y="278" width="210" height="92"/>
+ <!-- Table top -->
+ <rect class="fill-wall-light" x="98" y="298" width="216" height="10"/>
+ <!-- Table legs -->
+ <rect class="fill-wall-dark" x="108" y="308" width="10" height="62"/>
+ <rect class="fill-wall-dark" x="294" y="308" width="10" height="62"/>
+ <!-- Cross brace -->
+ <rect class="fill-wall-dark" x="118" y="340" width="176" height="4"/>
+ <!-- Sample tiles on surface -->
+ <rect class="fill-accent-dim" x="120" y="288" width="20" height="10"/>
+ <rect class="fill-window" x="150" y="290" width="15" height="8"/>
+ <rect class="fill-board" x="175" y="289" width="18" height="9"/>
+ <!-- Ruler/straight edge -->
+ <rect class="fill-wall" x="210" y="292" width="80" height="4"/>
+ <text class="hotspot-label" x="205" y="270" text-anchor="middle">技法</text>
+ </a>
+
+ <!-- ============================
+ 14. Hotspot: Material crates 材料 (floor)
+ ============================ -->
+ <a class="hotspot" href="#panel-materials" aria-label="材料 — Materials">
+ <title>材料 — Materials</title>
+ <rect class="hotspot-shape" x="98" y="383" width="165" height="100"/>
+ <!-- Large crate (back) -->
+ <rect class="fill-wall" x="105" y="395" width="70" height="55"/>
+ <rect class="fill-wall-dark" x="105" y="395" width="70" height="5"/>
+ <!-- Plank lines -->
+ <rect class="fill-wall-dark" x="105" y="416" width="70" height="2"/>
+ <rect class="fill-wall-dark" x="105" y="436" width="70" height="2"/>
+ <!-- Small crate (front, overlapping) -->
+ <rect class="fill-wall-dark" x="130" y="420" width="50" height="40"/>
+ <rect class="fill-wall" x="130" y="420" width="50" height="4"/>
+ <!-- Open crate with ore -->
+ <rect class="fill-wall" x="190" y="400" width="60" height="50"/>
+ <rect class="fill-wall-dark" x="190" y="400" width="60" height="4"/>
+ <!-- Ore chunks visible -->
+ <rect class="fill-accent-dim" x="200" y="412" width="12" height="10"/>
+ <rect class="fill-accent-dim" x="218" y="414" width="10" height="8"/>
+ <rect class="fill-accent-dim" x="234" y="410" width="8" height="12"/>
+ <text class="hotspot-label" x="180" y="378" text-anchor="middle">材料</text>
+ </a>
+
+ <!-- ============================
+ 15. Return door → interior.html
+ ============================ -->
+ <a class="hotspot" href="interior.html" aria-label="返回城堡 — Return to castle interior">
+ <title>返回城堡 — Return to castle interior</title>
+ <rect class="hotspot-shape" x="350" y="450" width="100" height="45" rx="4"/>
+ <text class="hotspot-label" x="400" y="478" text-anchor="middle">返回城堡</text>
+ </a>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-workshop" class="scene-nav" aria-label="工坊导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="#panel-tools">工具 — 工具架</a></li>
+ <li><a class="scene-nav__link" href="#panel-blueprint">蓝图 — 设计蓝图</a></li>
+ <li><a class="scene-nav__link" href="#panel-forging">锻造 — 部署流程</a></li>
+ <li><a class="scene-nav__link" href="#panel-techniques">技法 — 设计技法</a></li>
+ <li><a class="scene-nav__link" href="#panel-materials">材料 — 构建材料</a></li>
+ <li><a class="scene-nav__link" href="interior.html">返回城堡</a></li>
+ </ul>
+ </nav>
+
+ <!-- ============================================================
+ :target overlay panels — Close-up SVG scenes
+ ============================================================ -->
+
+ <!-- ======================== 1. 工具 Tool Rack ======================== -->
+ <div id="panel-tools" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-tools-title" viewBox="0 0 600 400">
+ <title id="closeup-tools-title">工具架特写</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="400"/>
+ <!-- Backboard -->
+ <rect class="fill-wall" x="40" y="30" width="520" height="340"/>
+ <!-- Shelves -->
+ <rect class="fill-wall-light" x="40" y="100" width="520" height="8"/>
+ <rect class="fill-wall-light" x="40" y="210" width="520" height="8"/>
+ <rect class="fill-wall-light" x="40" y="320" width="520" height="8"/>
+ <!-- Pegs -->
+ <rect class="fill-wall-dark" x="100" y="36" width="6" height="12" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="250" y="36" width="6" height="12" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="400" y="36" width="6" height="12" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="26" text-anchor="middle">工具</text>
+
+ <!-- Item: Git (hammer) -->
+ <g id="tools-git" class="closeup-item">
+ <a href="#tools-git" aria-label="Git — 版本控制与部署触发">
+ <title>Git — 版本控制与部署触发</title>
+ <rect class="closeup-item__shape" x="60" y="48" width="110" height="48" rx="4"/>
+ <!-- Hammer shape -->
+ <rect class="fill-door" x="100" y="56" width="6" height="34"/>
+ <rect class="fill-door" x="90" y="54" width="26" height="10"/>
+ <text class="closeup-item__name" x="115" y="106" text-anchor="middle">Git</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="60" y="112" width="200" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="72" y="134">Git</text>
+ <text class="closeup-desc__text" x="72" y="152">版本控制与部署触发</text>
+ </g>
+ </g>
+
+ <!-- Item: Caddy (shield) -->
+ <g id="tools-caddy" class="closeup-item">
+ <a href="#tools-caddy" aria-label="Caddy — Web 服务器与反向代理">
+ <title>Caddy — Web 服务器与反向代理</title>
+ <rect class="closeup-item__shape" x="200" y="48" width="110" height="48" rx="4"/>
+ <!-- Shield shape -->
+ <polygon class="fill-door" points="255,54 275,54 275,78 265,86 255,78"/>
+ <text class="closeup-item__name" x="265" y="106" text-anchor="middle">Caddy</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="200" y="112" width="220" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="212" y="134">Caddy</text>
+ <text class="closeup-desc__text" x="212" y="152">Web 服务器与反向代理</text>
+ </g>
+ </g>
+
+ <!-- Item: Sourcehut (gear) -->
+ <g id="tools-sourcehut" class="closeup-item">
+ <a href="#tools-sourcehut" aria-label="Sourcehut — 自建 Git 托管">
+ <title>Sourcehut — 自建 Git 托管</title>
+ <rect class="closeup-item__shape" x="60" y="158" width="110" height="48" rx="4"/>
+ <!-- Gear shape -->
+ <rect class="fill-door" x="95" y="164" width="30" height="30"/>
+ <rect class="fill-door" x="103" y="160" width="14" height="38"/>
+ <rect class="fill-wall" x="103" y="172" width="14" height="14"/>
+ <text class="closeup-item__name" x="115" y="216" text-anchor="middle">Sourcehut</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="60" y="222" width="200" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="72" y="244">Sourcehut</text>
+ <text class="closeup-desc__text" x="72" y="262">自建 Git 托管</text>
+ </g>
+ </g>
+
+ <!-- Item: Hexo (pen) -->
+ <g id="tools-hexo" class="closeup-item">
+ <a href="#tools-hexo" aria-label="Hexo — 博客静态生成器">
+ <title>Hexo — 博客静态生成器</title>
+ <rect class="closeup-item__shape" x="200" y="158" width="110" height="48" rx="4"/>
+ <!-- Pen shape -->
+ <rect class="fill-door" x="249" y="164" width="6" height="30"/>
+ <polygon class="fill-door" points="249,194 255,194 252,202"/>
+ <rect class="fill-door" x="245" y="162" width="14" height="5"/>
+ <text class="closeup-item__name" x="255" y="216" text-anchor="middle">Hexo</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="200" y="222" width="200" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="212" y="244">Hexo</text>
+ <text class="closeup-desc__text" x="212" y="262">博客静态生成器</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 2. 材料 Material Crates ======================== -->
+ <div id="panel-materials" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-materials-title" viewBox="0 0 600 400">
+ <title id="closeup-materials-title">材料箱特写</title>
+
+ <!-- Background -->
+ <rect class="fill-ground" width="600" height="400"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="30" text-anchor="middle">材料</text>
+
+ <!-- Crate backgrounds (decorative) -->
+ <rect class="fill-wall-dark" x="30" y="50" width="250" height="145" rx="4" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="320" y="50" width="250" height="145" rx="4" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="30" y="220" width="250" height="145" rx="4" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="320" y="220" width="250" height="145" rx="4" aria-hidden="true"/>
+ <!-- Crate lids -->
+ <rect class="fill-wall" x="30" y="50" width="250" height="8" rx="2" aria-hidden="true"/>
+ <rect class="fill-wall" x="320" y="50" width="250" height="8" rx="2" aria-hidden="true"/>
+ <rect class="fill-wall" x="30" y="220" width="250" height="8" rx="2" aria-hidden="true"/>
+ <rect class="fill-wall" x="320" y="220" width="250" height="8" rx="2" aria-hidden="true"/>
+
+ <!-- Item: HTML (rectangular block) -->
+ <g id="materials-html" class="closeup-item">
+ <a href="#materials-html" aria-label="HTML — 纯 HTML + CSS,极少 JavaScript">
+ <title>纯 HTML + CSS,极少 JavaScript</title>
+ <rect class="closeup-item__shape" x="52" y="72" width="206" height="70" rx="4"/>
+ <!-- Block shape -->
+ <rect class="fill-door" x="110" y="86" width="90" height="40" rx="2"/>
+ <text class="closeup-item__name" x="155" y="156" text-anchor="middle">HTML + CSS</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="52" y="162" width="226" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="64" y="182">纯 HTML + CSS,极少 JavaScript</text>
+ </g>
+ </g>
+
+ <!-- Item: SVG (diamond crystal) -->
+ <g id="materials-svg" class="closeup-item">
+ <a href="#materials-svg" aria-label="SVG — 所有 SVG 直接内联于 DOM">
+ <title>所有 SVG 直接内联于 DOM</title>
+ <rect class="closeup-item__shape" x="342" y="72" width="206" height="70" rx="4"/>
+ <!-- Diamond shape -->
+ <polygon class="fill-door" points="445,82 465,105 445,128 425,105"/>
+ <text class="closeup-item__name" x="445" y="156" text-anchor="middle">Inline SVG</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="342" y="162" width="226" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="354" y="182">所有 SVG 直接内联于 DOM</text>
+ </g>
+ </g>
+
+ <!-- Item: CSS interactions (gear piece) -->
+ <g id="materials-css" class="closeup-item">
+ <a href="#materials-css" aria-label="CSS — :target · :hover · checkbox hack">
+ <title>:target · :hover · checkbox hack</title>
+ <rect class="closeup-item__shape" x="52" y="242" width="206" height="70" rx="4"/>
+ <!-- Gear piece -->
+ <rect class="fill-door" x="136" y="252" width="38" height="38"/>
+ <rect class="fill-door" x="144" y="248" width="22" height="46"/>
+ <rect class="fill-wall-dark" x="148" y="264" width="14" height="14"/>
+ <text class="closeup-item__name" x="155" y="326" text-anchor="middle">CSS 交互</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="52" y="332" width="226" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="64" y="352">:target · :hover · checkbox hack</text>
+ </g>
+ </g>
+
+ <!-- Item: No build (seal/stamp) -->
+ <g id="materials-nobuild" class="closeup-item">
+ <a href="#materials-nobuild" aria-label="无构建 — 无构建工具、无打包器">
+ <title>无构建工具、无打包器</title>
+ <rect class="closeup-item__shape" x="342" y="242" width="206" height="70" rx="4"/>
+ <!-- Stamp shape -->
+ <rect class="fill-door" x="425" y="252" width="40" height="8"/>
+ <rect class="fill-door" x="438" y="260" width="14" height="16"/>
+ <rect class="fill-door" x="420" y="276" width="50" height="20" rx="2"/>
+ <text class="closeup-item__name" x="445" y="326" text-anchor="middle">零构建</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="342" y="332" width="226" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="354" y="352">无构建工具、无打包器</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 3. 技法 Workbench ======================== -->
+ <div id="panel-techniques" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-techniques-title" viewBox="0 0 600 400">
+ <title id="closeup-techniques-title">工作台特写</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="400"/>
+ <!-- Table surface -->
+ <rect class="fill-wall-light" x="20" y="60" width="560" height="280"/>
+ <!-- Table legs visible at edges -->
+ <rect class="fill-wall-dark" x="30" y="340" width="16" height="60" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="554" y="340" width="16" height="60" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="40" text-anchor="middle">技法</text>
+
+ <!-- Item: oklch colors (color swatches) -->
+ <g id="techniques-oklch" class="closeup-item">
+ <a href="#techniques-oklch" aria-label="oklch — 深冷色调背景与橙色强调">
+ <title>深冷色调背景与橙色强调</title>
+ <rect class="closeup-item__shape" x="40" y="80" width="240" height="100" rx="4"/>
+ <!-- Color swatches -->
+ <rect class="fill-sky" x="60" y="96" width="40" height="40"/>
+ <rect class="fill-mountain" x="108" y="96" width="40" height="40"/>
+ <rect class="fill-ground" x="156" y="96" width="40" height="40"/>
+ <rect class="fill-accent-shape" x="204" y="96" width="40" height="40"/>
+ <text class="closeup-item__name" x="160" y="194" text-anchor="middle">oklch 色彩</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="200" width="240" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="220">oklch</text>
+ <text class="closeup-desc__text" x="52" y="236">深冷色调背景与橙色强调</text>
+ </g>
+ </g>
+
+ <!-- Item: flat geometry (tile) -->
+ <g id="techniques-flat" class="closeup-item">
+ <a href="#techniques-flat" aria-label="扁平几何 — 纯填充,无描边无渐变">
+ <title>纯填充,无描边无渐变</title>
+ <rect class="closeup-item__shape" x="320" y="80" width="240" height="100" rx="4"/>
+ <!-- Flat geometry tiles -->
+ <rect class="fill-door" x="350" y="100" width="60" height="60"/>
+ <rect class="fill-wall" x="420" y="100" width="40" height="30"/>
+ <rect class="fill-board" x="420" y="136" width="40" height="24"/>
+ <polygon class="fill-accent-dim" points="470,100 530,100 500,160"/>
+ <text class="closeup-item__name" x="440" y="194" text-anchor="middle">扁平几何</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="320" y="200" width="240" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="332" y="220">扁平几何</text>
+ <text class="closeup-desc__text" x="332" y="236">纯填充,无描边无渐变</text>
+ </g>
+ </g>
+
+ <!-- Item: fire technique (3-layer sample) -->
+ <g id="techniques-fire" class="closeup-item">
+ <a href="#techniques-fire" aria-label="三层火焰 — 辉光→半透明→实色核心">
+ <title>辉光→半透明→实色核心</title>
+ <rect class="closeup-item__shape" x="40" y="256" width="240" height="70" rx="4"/>
+ <!-- 3-layer fire sample -->
+ <rect class="fill-window-glow" x="110" y="264" width="80" height="48"/>
+ <rect class="fill-window" x="122" y="272" width="56" height="32"/>
+ <rect class="fill-accent-shape" x="134" y="280" width="32" height="20"/>
+ <text class="closeup-item__name" x="160" y="342" text-anchor="middle">三层火焰</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="332" width="260" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="352">三层火焰</text>
+ <text class="closeup-desc__text" x="52" y="368">辉光 → 半透明 → 实色核心</text>
+ </g>
+ </g>
+
+ <!-- Item: accessibility (a11y symbol) -->
+ <g id="techniques-a11y" class="closeup-item">
+ <a href="#techniques-a11y" aria-label="无障碍 — prefers-reduced-motion + aria">
+ <title>prefers-reduced-motion + aria</title>
+ <rect class="closeup-item__shape" x="320" y="256" width="240" height="70" rx="4"/>
+ <!-- Accessibility: human figure -->
+ <circle class="fill-door" cx="440" cy="270" r="8"/>
+ <rect class="fill-door" x="436" y="280" width="8" height="24"/>
+ <rect class="fill-door" x="424" y="286" width="32" height="6"/>
+ <text class="closeup-item__name" x="440" y="342" text-anchor="middle">无障碍</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="320" y="332" width="260" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="332" y="352">无障碍</text>
+ <text class="closeup-desc__text" x="332" y="368">prefers-reduced-motion + aria</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 4. 锻造 Forge ======================== -->
+ <div id="panel-forging" class="capsule-panel" tabindex="-1">
+ <svg class="closeup closeup--forge" role="img" aria-labelledby="closeup-forging-title" viewBox="0 0 600 400">
+ <title id="closeup-forging-title">锻造流程特写</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="400"/>
+
+ <!-- Hearth stone frame -->
+ <rect class="fill-wall" x="40" y="280" width="520" height="110" rx="4"/>
+ <!-- Fire recess (dark opening) -->
+ <rect class="fill-door" x="60" y="80" width="480" height="280"/>
+ <!-- Hearth ledge -->
+ <rect class="fill-wall-light" x="40" y="275" width="520" height="10"/>
+ <!-- Shared coals at base -->
+ <rect class="fill-accent-shape" x="80" y="340" width="440" height="20" rx="2"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="28" text-anchor="middle">锻造</text>
+
+ <!-- Flames rendered back → front (painter's algorithm) -->
+
+ <!-- Layer 4 (backmost): Sourcehut mirror -->
+ <g id="forging-mirror" class="closeup-item">
+ <a href="#forging-mirror" aria-label="镜像 — 推送至 Sourcehut 镜像">
+ <title>推送至 Sourcehut 镜像</title>
+ <!-- Outer glow -->
+ <polygon class="fill-fire-4-glow" points="420,340 540,340 510,120 450,120"/>
+ <!-- Semi-transparent body -->
+ <polygon class="fill-fire-4-body" points="435,340 525,340 505,140 455,140"/>
+ <!-- Solid core -->
+ <polygon class="fill-fire-4-core" points="455,340 505,340 495,180 465,180"/>
+ <text class="closeup-item__name" x="480" y="370" text-anchor="middle">镜像</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="150" y="150" width="300" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="170" y="172">Sourcehut</text>
+ <text class="closeup-desc__text" x="170" y="192">推送至 Sourcehut 镜像</text>
+ </g>
+ </g>
+
+ <!-- Layer 3: rsync -->
+ <g id="forging-rsync" class="closeup-item">
+ <a href="#forging-rsync" aria-label="同步 — rsync 至 /var/www/realm">
+ <title>rsync 至 /var/www/realm</title>
+ <polygon class="fill-fire-3-glow" points="310,340 460,340 420,100 350,100"/>
+ <polygon class="fill-fire-3-body" points="325,340 445,340 415,125 355,125"/>
+ <polygon class="fill-fire-3-core" points="345,340 425,340 405,165 365,165"/>
+ <text class="closeup-item__name" x="385" y="370" text-anchor="middle">rsync</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="150" y="150" width="300" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="170" y="172">rsync</text>
+ <text class="closeup-desc__text" x="170" y="192">同步至 /var/www/realm</text>
+ </g>
+ </g>
+
+ <!-- Layer 2: post-receive hook -->
+ <g id="forging-hook" class="closeup-item">
+ <a href="#forging-hook" aria-label="钩子 — post-receive 检出与构建">
+ <title>post-receive 检出与构建</title>
+ <polygon class="fill-fire-2-glow" points="200,340 380,340 340,90 240,90"/>
+ <polygon class="fill-fire-2-body" points="218,340 362,340 332,115 248,115"/>
+ <polygon class="fill-fire-2-core" points="240,340 340,340 320,155 260,155"/>
+ <text class="closeup-item__name" x="290" y="370" text-anchor="middle">post-receive</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="150" y="150" width="300" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="170" y="172">post-receive</text>
+ <text class="closeup-desc__text" x="170" y="192">检出与构建</text>
+ </g>
+ </g>
+
+ <!-- Layer 1 (frontmost): git push -->
+ <g id="forging-push" class="closeup-item">
+ <a href="#forging-push" aria-label="推送 — git push 推送至裸仓库">
+ <title>git push 推送至裸仓库</title>
+ <polygon class="fill-window-glow" points="80,340 290,340 250,80 120,80"/>
+ <polygon class="fill-window" points="100,340 270,340 240,105 130,105"/>
+ <polygon class="fill-accent-shape" points="125,340 245,340 225,145 145,145"/>
+ <text class="closeup-item__name" x="185" y="370" text-anchor="middle">git push</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="150" y="150" width="300" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="170" y="172">git push</text>
+ <text class="closeup-desc__text" x="170" y="192">推送至裸仓库</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 5. 蓝图 Blueprint ======================== -->
+ <div id="panel-blueprint" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-blueprint-title" viewBox="0 0 600 400">
+ <title id="closeup-blueprint-title">蓝图特写</title>
+
+ <!-- Background parchment -->
+ <rect class="fill-board" width="600" height="400" rx="4"/>
+ <!-- Pin at top -->
+ <circle class="fill-accent-shape" cx="300" cy="16" r="6"/>
+ <!-- Border lines -->
+ <rect class="fill-path" x="15" y="15" width="570" height="2" aria-hidden="true"/>
+ <rect class="fill-path" x="15" y="383" width="570" height="2" aria-hidden="true"/>
+ <rect class="fill-path" x="15" y="15" width="2" height="370" aria-hidden="true"/>
+ <rect class="fill-path" x="583" y="15" width="2" height="370" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="48" text-anchor="middle">蓝图</text>
+
+ <!-- Dividing lines (cross pattern) -->
+ <rect class="fill-path" x="300" y="60" width="2" height="320" aria-hidden="true"/>
+ <rect class="fill-path" x="20" y="210" width="560" height="2" aria-hidden="true"/>
+
+ <!-- Item: @layer (top-left section) -->
+ <g id="blueprint-layer" class="closeup-item">
+ <a href="#blueprint-layer" aria-label="@layer — 级联控制层顺序">
+ <title>@layer 级联控制层顺序</title>
+ <rect class="closeup-item__shape" x="25" y="66" width="268" height="136" rx="4"/>
+ <!-- Layer diagram -->
+ <rect class="fill-path" x="80" y="90" width="160" height="16"/>
+ <rect class="fill-path" x="80" y="112" width="160" height="16"/>
+ <rect class="fill-path" x="80" y="134" width="160" height="16"/>
+ <rect class="fill-path" x="80" y="156" width="160" height="16"/>
+ <text class="closeup-item__name" x="159" y="190" text-anchor="middle">@layer</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="118" width="244" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="138">@layer</text>
+ <text class="closeup-desc__text" x="52" y="154">级联控制层顺序</text>
+ </g>
+ </g>
+
+ <!-- Item: @property (top-right section) -->
+ <g id="blueprint-property" class="closeup-item">
+ <a href="#blueprint-property" aria-label="@property — oklch 颜色插值">
+ <title>@property oklch 颜色插值</title>
+ <rect class="closeup-item__shape" x="310" y="66" width="268" height="136" rx="4"/>
+ <!-- Color interpolation diagram -->
+ <rect class="fill-sky" x="360" y="100" width="30" height="30"/>
+ <rect class="fill-path" x="400" y="110" width="30" height="10"/>
+ <rect class="fill-wall" x="440" y="100" width="30" height="30"/>
+ <rect class="fill-path" x="480" y="110" width="30" height="10"/>
+ <rect class="fill-accent-shape" x="520" y="100" width="30" height="30"/>
+ <text class="closeup-item__name" x="444" y="190" text-anchor="middle">@property</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="324" y="118" width="244" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="336" y="138">@property</text>
+ <text class="closeup-desc__text" x="336" y="154">oklch 颜色插值</text>
+ </g>
+ </g>
+
+ <!-- Item: symbol + use (bottom-left section) -->
+ <g id="blueprint-svg" class="closeup-item">
+ <a href="#blueprint-svg" aria-label="SVG — symbol + use 响应式复用">
+ <title>symbol + use 响应式复用</title>
+ <rect class="closeup-item__shape" x="25" y="220" width="268" height="160" rx="4"/>
+ <!-- Symbol + use diagram -->
+ <rect class="fill-path" x="60" y="250" width="60" height="50"/>
+ <rect class="fill-wall-dark" x="68" y="258" width="44" height="34"/>
+ <rect class="fill-path" x="60" y="310" width="30" height="24"/>
+ <rect class="fill-path" x="100" y="310" width="30" height="24"/>
+ <rect class="fill-path" x="140" y="310" width="30" height="24"/>
+ <text class="closeup-item__name" x="159" y="360" text-anchor="middle">symbol + use</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="290" width="244" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="310">symbol + use</text>
+ <text class="closeup-desc__text" x="52" y="326">响应式复用</text>
+ </g>
+ </g>
+
+ <!-- Item: hotspot + panel (bottom-right section) -->
+ <g id="blueprint-system" class="closeup-item">
+ <a href="#blueprint-system" aria-label="交互系统 — hotspot + panel 交互系统">
+ <title>hotspot + panel 交互系统</title>
+ <rect class="closeup-item__shape" x="310" y="220" width="268" height="160" rx="4"/>
+ <!-- Hotspot + panel diagram -->
+ <rect class="fill-path" x="350" y="250" width="80" height="60"/>
+ <rect class="fill-accent-dim" x="358" y="258" width="20" height="16"/>
+ <rect class="fill-accent-dim" x="386" y="258" width="20" height="16"/>
+ <rect class="fill-path" x="460" y="250" width="60" height="80"/>
+ <rect class="fill-wall-dark" x="466" y="258" width="48" height="64"/>
+ <text class="closeup-item__name" x="444" y="360" text-anchor="middle">hotspot + panel</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="324" y="290" width="244" height="44" rx="4"/>
+ <text class="closeup-desc__label" x="336" y="310">交互系统</text>
+ <text class="closeup-desc__text" x="336" y="326">hotspot + panel 交互系统</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ </main>
+
+</body>
+</html>
M pages/contact.html => pages/contact.html +171 -14
@@ 1,32 1,189 @@
<!DOCTYPE html>
-<html lang="en">
+<html lang="zh-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contact — Realm</title>
<meta name="description" content="领地联络处 — Contact the Realm">
<meta name="theme-color" content="#1a1a2e">
- <link rel="stylesheet" href="/css/realm.css">
+ <link rel="stylesheet" href="../css/realm.css">
</head>
<body>
- <main class="realm">
- <header class="realm-sigil">
- <h1 class="realm-sigil__title">领地联络处</h1>
- <p class="realm-sigil__subtitle">Contact</p>
- </header>
+ <a class="skip-link" href="#main-content">跳至正文</a>
- <div class="realm-panel">
- <p>Reach out via the channels listed below.</p>
- <!-- Add contact methods here -->
+ <main class="realm-scene" style="--scene-bg: oklch(0.25 0.04 278)">
+ <h1 class="visually-hidden">联络处</h1>
+ <div class="realm-scene__content">
+ <div id="main-content" class="phone-scene">
+ <div class="phone-booth">
+ <!-- 纸条堆叠 -->
+ <div class="phone-note-stack">
+ <!-- 上层纸条:号码表 -->
+ <aside class="phone-note">
+ <p class="phone-note__title">以防我忘记……</p>
+ <dl class="phone-note__list">
+ <dt>114</dt><dd>电子邮箱</dd>
+ <dt>520</dt><dd>长毛象</dd>
+ <dt>404</dt><dd>GitHub</dd>
+ <dt>818</dt><dd>Pixelfed(新)</dd>
+ <dt>886</dt><dd>Pixelfed(旧)</dd>
+ <dt>010</dt><dd>Matrix</dd>
+ </dl>
+ </aside>
+
+ <!-- 下层纸条:使用说明(checkbox hack) -->
+ <input type="checkbox" id="phone-hint-toggle" class="phone-hint-toggle">
+ <div class="phone-hint">
+ <div class="phone-hint__body">
+ <p>这种电话是需要将听筒拿起来才能拨号的。</p>
+ <ol>
+ <li>拿起左侧听筒(点击听筒按钮)</li>
+ <li>听到提示音后,按键盘上的数字</li>
+ <li>拨满三位后等待接通</li>
+ <li>打完电话记得挂回听筒</li>
+ </ol>
+ </div>
+ <label for="phone-hint-toggle" class="phone-hint__tab" aria-label="展开使用说明">?</label>
+ </div>
+ </div>
+
+ <!-- 电话主体 -->
+ <div class="phone" data-state="idle">
+ <!-- 雨棚 -->
+ <div class="phone-hood"></div>
+
+ <!-- 机身 -->
+ <div class="phone-body">
+ <!-- 听筒(点击拿起/挂断)-->
+ <button class="phone-handset" type="button" aria-label="拿起听筒"></button>
+
+ <!-- 显示屏 -->
+ <div class="phone-display">
+ <span class="phone-display__digits"></span>
+ <span class="phone-display__status" aria-live="polite"></span>
+ <!-- 拨号结果(显示在屏幕内) -->
+ <div class="phone-result" hidden aria-live="polite">
+ <a class="phone-result__link" href=""></a>
+ </div>
+ </div>
+
+ <!-- 键盘 3×4 -->
+ <div class="phone-keypad">
+ <button class="phone-key" type="button" data-digit="1">1</button>
+ <button class="phone-key" type="button" data-digit="2">2</button>
+ <button class="phone-key" type="button" data-digit="3">3</button>
+ <button class="phone-key" type="button" data-digit="4">4</button>
+ <button class="phone-key" type="button" data-digit="5">5</button>
+ <button class="phone-key" type="button" data-digit="6">6</button>
+ <button class="phone-key" type="button" data-digit="7">7</button>
+ <button class="phone-key" type="button" data-digit="8">8</button>
+ <button class="phone-key" type="button" data-digit="9">9</button>
+ <button class="phone-key" type="button" data-digit="*">*</button>
+ <button class="phone-key" type="button" data-digit="0">0</button>
+ <button class="phone-key" type="button" data-digit="#">#</button>
+ </div>
+
+ <!-- 投币口 -->
+ <div class="phone-coin"></div>
+ </div>
+
+ <!-- 搁物台 -->
+ <div class="phone-shelf"></div>
+ </div>
+ </div>
+ </div>
</div>
- <nav class="realm-nav" style="margin-top:var(--space-xl)">
- <a href="/">
- ← 返回领地
- </a>
+ <!-- 无 JS 降级:直接显示联系方式 -->
+ <noscript>
+ <div class="realm-content">
+ <p>电子邮箱:<a href="mailto:boo@cytrogen.icu">boo@cytrogen.icu</a></p>
+ <p>长毛象:<a href="https://m.otter.homes/@Cytrogen">@Cytrogen@m.otter.homes</a></p>
+ <p>GitHub:<a href="https://github.com/cytrogen">github.com/cytrogen</a></p>
+ </div>
+ </noscript>
+
+ <nav class="realm-scene__nav realm-nav">
+ <a href="castle.html">← 返回领地</a>
</nav>
</main>
+ <script>
+ (() => {
+ const phone = document.querySelector('.phone');
+ const digits = phone.querySelector('.phone-display__digits');
+ const status = phone.querySelector('.phone-display__status');
+ const result = phone.querySelector('.phone-result');
+ const link = phone.querySelector('.phone-result__link');
+ const codes = {
+ '114': { label: 'boo@cytrogen.icu', href: 'mailto:boo@cytrogen.icu' },
+ '520': { label: '@Cytrogen@m.otter.homes', href: 'https://m.otter.homes/@Cytrogen' },
+ '404': { label: 'github.com/cytrogen', href: 'https://github.com/cytrogen' },
+ '818': { label: '@Cytrogen@pixelfed.feddit.social', href: 'https://pixelfed.feddit.social/Cytrogen' },
+ '886': { label: '@Cytrogen@pxlmo.com', href: 'https://pxlmo.com/Cytrogen' },
+ '010': { label: '@cytrogen:tchncs.de', href: 'https://matrix.to/#/@cytrogen:tchncs.de' },
+ };
+ let timer = null;
+
+ function setState(s) {
+ phone.dataset.state = s;
+ phone.querySelector('.phone-handset').ariaLabel =
+ s === 'idle' ? '拿起听筒' : '挂断听筒';
+ const keysDisabled = s !== 'ready';
+ phone.querySelectorAll('.phone-key').forEach(k => k.disabled = keysDisabled);
+ }
+
+ function reset() {
+ clearTimeout(timer);
+ digits.textContent = '';
+ status.textContent = '';
+ status.hidden = false;
+ result.hidden = true;
+ link.href = '';
+ link.textContent = '';
+ setState('idle');
+ }
+
+ phone.querySelector('.phone-handset').addEventListener('click', () => {
+ if (phone.dataset.state === 'idle') {
+ setState('ready');
+ status.textContent = '请拨号…';
+ } else {
+ reset();
+ }
+ });
+
+ phone.querySelector('.phone-keypad').addEventListener('click', (e) => {
+ const key = e.target.closest('[data-digit]');
+ if (!key || phone.dataset.state !== 'ready') return;
+ digits.textContent += key.dataset.digit;
+ if (digits.textContent.length < 3) return;
+
+ const num = digits.textContent;
+ const entry = codes[num];
+ if (entry) {
+ setState('connecting');
+ status.textContent = '拨号中…';
+ timer = setTimeout(() => {
+ setState('connected');
+ status.hidden = true;
+ link.href = entry.href;
+ link.textContent = entry.label;
+ result.hidden = false;
+ }, 1500);
+ } else {
+ setState('error');
+ status.textContent = '空号';
+ timer = setTimeout(() => {
+ digits.textContent = '';
+ status.textContent = '请拨号…';
+ setState('ready');
+ }, 2000);
+ }
+ });
+ })();
+ </script>
+
</body>
</html>
A pages/death.html => pages/death.html +56 -0
@@ 0,0 1,56 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>遗言 — Realm</title>
+ <meta name="description" content="遗言 — Death page of the Realm">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#content">跳过场景</a>
+
+ <main class="realm-scene" style="--scene-bg: oklch(0.12 0.03 290)">
+ <h1 class="visually-hidden">遗言</h1>
+ <div class="realm-scene__content">
+ <div class="realm-scene__backdrop">
+ <svg role="img" aria-labelledby="death-title" viewBox="0 0 400 500">
+ <title id="death-title">遗言 — 墓碑</title>
+
+ <!-- Sky background -->
+ <rect class="fill-sky" x="0" y="0" width="400" height="500"/>
+
+ <!-- Ground -->
+ <rect class="fill-ground" x="0" y="380" width="400" height="120"/>
+
+ <!-- Tombstone -->
+ <path fill="oklch(0.28 0.04 278)" d="
+ M80 380 L80 140
+ Q80 60 200 50
+ Q320 60 320 140
+ L320 380 Z
+ "/>
+
+ <!-- Engraved epitaph text -->
+ <text fill="oklch(0.42 0.03 285)" text-anchor="middle" font-family="system-ui, sans-serif">
+ <tspan x="200" y="180" font-size="18">冒险模式 LEVEL 1-1</tspan>
+ <tspan x="200" y="220" font-size="18">玩玩小游戏</tspan>
+ <tspan x="200" y="260" font-size="18">解密模式</tspan>
+ <tspan x="200" y="300" font-size="18">生存模式</tspan>
+ </text>
+
+ <!-- Ground mound at base -->
+ <path class="fill-ground" d="M40 380 Q200 360 360 380 Z"/>
+ </svg>
+ </div>
+ </div>
+
+ <nav id="content" class="realm-scene__nav realm-nav">
+ <a href="castle.html">← 返回领地</a>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/friends.html => pages/friends.html +31 -0
@@ 0,0 1,31 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>友邻 — Realm</title>
+ <meta name="description" content="友邻 — Friends of the Realm">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#main-content">跳至正文</a>
+
+ <main class="realm">
+ <header class="realm-sigil">
+ <h1 class="realm-sigil__title">友邻</h1>
+ <p class="realm-sigil__subtitle">Friends</p>
+ </header>
+
+ <div id="main-content" class="realm-content">
+ <p>Allies and neighbors of the realm.</p>
+ </div>
+
+ <nav class="realm-nav" style="margin-top:var(--space-xl)">
+ <a href="neighbors.html">← 返回领地</a>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/hosted.html => pages/hosted.html +214 -0
@@ 0,0 1,214 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>属地 — Realm</title>
+ <meta name="description" content="属地 — Hosted services of the Realm">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-hosted">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">属地</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-hosted-title" viewBox="0 0 800 500">
+ <title id="scene-hosted-title">属地 — Walled manor with code repository, monitoring tower, and post office</title>
+
+ <!-- Sky -->
+ <rect class="fill-sky" x="0" y="0" width="800" height="500"/>
+
+ <!-- Stars -->
+ <g class="scene-detail" aria-hidden="true">
+ <rect class="fill-star" x="60" y="25" width="3" height="3"/>
+ <rect class="fill-star" x="180" y="50" width="2" height="2"/>
+ <rect class="fill-star" x="310" y="15" width="3" height="3"/>
+ <rect class="fill-star" x="450" y="40" width="2" height="2"/>
+ <rect class="fill-star" x="570" y="20" width="2" height="2"/>
+ <rect class="fill-star" x="650" y="55" width="3" height="3"/>
+ <rect class="fill-star" x="130" y="75" width="2" height="2"/>
+ <rect class="fill-star" x="740" y="35" width="2" height="2"/>
+ </g>
+
+ <!-- Moon -->
+ <circle class="fill-moon" cx="700" cy="75" r="28" aria-hidden="true"/>
+ <circle class="fill-sky" cx="714" cy="66" r="26" aria-hidden="true"/>
+
+ <!-- Distant mountains -->
+ <path class="fill-mountain-far" d="M0 270 L90 190 L180 230 L300 170 L420 210 L520 175 L630 225 L730 185 L800 215 L800 310 L0 310 Z" aria-hidden="true"/>
+ <path class="fill-mountain" d="M0 300 L70 250 L160 280 L260 230 L360 265 L480 220 L580 270 L680 245 L800 280 L800 330 L0 330 Z" aria-hidden="true"/>
+
+ <!-- Ground -->
+ <rect class="fill-ground" x="0" y="310" width="800" height="190"/>
+
+ <!-- ============================
+ Manor walls + battlements
+ ============================ -->
+
+ <!-- Main wall body -->
+ <rect class="fill-wall" x="160" y="280" width="480" height="100" aria-hidden="true"/>
+
+ <!-- Battlements (crenellation) -->
+ <path class="fill-wall" d="
+ M160 280 L160 265 L185 265 L185 258 L210 258 L210 265
+ L235 265 L235 258 L260 258 L260 265 L285 265 L285 258 L310 258 L310 265
+ L335 265 L335 258 L360 258 L360 265 L385 265 L385 258 L410 258 L410 265
+ L435 265 L435 258 L460 258 L460 265 L485 265 L485 258 L510 258 L510 265
+ L535 265 L535 258 L560 258 L560 265 L585 265 L585 258 L610 258 L610 265
+ L640 265 L640 280 Z
+ " aria-hidden="true"/>
+
+ <!-- Wall detail bands -->
+ <rect class="fill-wall-dark" x="190" y="355" width="420" height="4" aria-hidden="true"/>
+ <rect class="fill-wall-light" x="190" y="330" width="420" height="3" aria-hidden="true"/>
+
+ <!-- ============================
+ Corner towers
+ ============================ -->
+
+ <!-- Left tower -->
+ <rect class="fill-wall-dark" x="140" y="230" width="50" height="150" aria-hidden="true"/>
+ <path class="fill-wall-dark" d="M140 230 L140 215 L152 215 L152 207 L165 198 L178 207 L178 215 L190 215 L190 230 Z" aria-hidden="true"/>
+ <rect class="fill-window" x="157" y="248" width="10" height="15" aria-hidden="true"/>
+ <rect class="fill-window" x="157" y="285" width="10" height="15" aria-hidden="true"/>
+
+ <!-- Right tower -->
+ <rect class="fill-wall-dark" x="610" y="230" width="50" height="150" aria-hidden="true"/>
+ <path class="fill-wall-dark" d="M610 230 L610 215 L622 215 L622 207 L635 198 L648 207 L648 215 L660 215 L660 230 Z" aria-hidden="true"/>
+ <rect class="fill-window" x="627" y="248" width="10" height="15" aria-hidden="true"/>
+ <rect class="fill-window" x="627" y="285" width="10" height="15" aria-hidden="true"/>
+
+ <!-- ============================
+ Gate (bottom center)
+ ============================ -->
+
+ <!-- Gate pillars -->
+ <rect class="fill-wall-dark" x="370" y="340" width="18" height="40" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="412" y="340" width="18" height="40" aria-hidden="true"/>
+
+ <!-- Gate lintel -->
+ <rect class="fill-wall-dark" x="365" y="335" width="70" height="12" aria-hidden="true"/>
+
+ <!-- Keystone -->
+ <polygon class="fill-accent-dim" points="395,335 405,335 403,328 397,328" aria-hidden="true"/>
+
+ <!-- ============================
+ HOTSPOT: 代码库 (Sourcehut)
+ ============================ -->
+ <a class="hotspot" href="https://git.cytrogen.icu" aria-label="代码库 — Sourcehut code repository">
+ <title>代码库 — Sourcehut</title>
+ <!-- Wide low warehouse with shallow roof -->
+ <rect class="hotspot-shape" x="200" y="290" width="130" height="55"/>
+ <polygon class="hotspot-shape" points="195,290 265,260 335,290"/>
+ <!-- Multiple narrow windows (code lines) -->
+ <rect class="fill-window" x="215" y="305" width="8" height="14"/>
+ <rect class="fill-window" x="230" y="305" width="8" height="14"/>
+ <rect class="fill-window" x="245" y="305" width="8" height="14"/>
+ <rect class="fill-window" x="260" y="305" width="8" height="14"/>
+ <rect class="fill-window" x="275" y="305" width="8" height="14"/>
+ <rect class="fill-window" x="290" y="305" width="8" height="14"/>
+ <!-- Door -->
+ <rect class="fill-door" x="305" y="325" width="16" height="20"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="265" y="253" text-anchor="middle">代码库</text>
+ </a>
+
+ <!-- ============================
+ HOTSPOT: 监控塔 (Beszel)
+ ============================ -->
+ <a class="hotspot" href="https://status.cytrogen.icu" aria-label="监控塔 — Beszel status monitoring">
+ <title>监控塔 — Beszel</title>
+ <!-- Tall narrow tower -->
+ <rect class="hotspot-shape" x="460" y="240" width="40" height="105"/>
+ <!-- Pointed spire -->
+ <polygon class="hotspot-shape" points="455,240 480,200 505,240"/>
+ <!-- Signal beacon at top (accent + glow) -->
+ <circle class="fill-accent-shape" cx="480" cy="212" r="5"/>
+ <circle class="fill-window-glow" cx="480" cy="212" r="10"/>
+ <!-- Vertical windows -->
+ <rect class="fill-window" x="473" y="258" width="10" height="12"/>
+ <rect class="fill-window" x="473" y="280" width="10" height="12"/>
+ <rect class="fill-window" x="473" y="302" width="10" height="12"/>
+ <rect class="fill-window" x="473" y="324" width="10" height="12"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="480" y="193" text-anchor="middle">监控塔</text>
+ </a>
+
+ <!-- ============================
+ HOTSPOT: 邮局 (Stalwart)
+ ============================ -->
+ <a class="hotspot" href="https://mail.cytrogen.icu" aria-label="邮局 — Stalwart mail server">
+ <title>邮局 — Stalwart</title>
+ <!-- Medium building -->
+ <rect class="hotspot-shape" x="535" y="275" width="70" height="70"/>
+ <!-- Peaked roof -->
+ <polygon class="hotspot-shape" points="530,275 570,248 610,275"/>
+ <!-- Flagpole -->
+ <rect class="hotspot-icon" x="590" y="238" width="3" height="37"/>
+ <!-- Flag (accent) -->
+ <polygon class="fill-accent-shape" points="593,241 612,247 593,253"/>
+ <!-- Windows -->
+ <rect class="fill-window" x="548" y="290" width="12" height="14"/>
+ <rect class="fill-window" x="578" y="290" width="12" height="14"/>
+ <!-- Door with mail slot -->
+ <rect class="fill-door" x="562" y="322" width="16" height="23"/>
+ <rect class="fill-accent-dim" x="565" y="330" width="10" height="3"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="570" y="241" text-anchor="middle">邮局</text>
+ </a>
+
+ <!-- Decorative trees -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left outside trees -->
+ <polygon class="fill-tree" points="50,340 65,285 80,340"/>
+ <polygon class="fill-tree" points="45,360 65,315 85,360"/>
+ <rect class="fill-tree" x="60" y="360" width="10" height="18"/>
+
+ <polygon class="fill-tree" points="105,345 118,300 131,345"/>
+ <polygon class="fill-tree" points="100,365 118,325 136,365"/>
+ <rect class="fill-tree" x="113" y="365" width="10" height="14"/>
+
+ <!-- Right outside trees -->
+ <polygon class="fill-tree" points="680,345 695,290 710,345"/>
+ <polygon class="fill-tree" points="675,365 695,320 715,365"/>
+ <rect class="fill-tree" x="690" y="365" width="10" height="18"/>
+
+ <polygon class="fill-tree" points="730,350 743,305 756,350"/>
+ <polygon class="fill-tree" points="725,370 743,330 761,370"/>
+ <rect class="fill-tree" x="738" y="370" width="10" height="22"/>
+
+ <!-- Far right small tree -->
+ <polygon class="fill-tree" points="770,355 780,325 790,355"/>
+ <rect class="fill-tree" x="775" y="355" width="8" height="12"/>
+ </g>
+
+ <!-- ============================
+ HOTSPOT: Road → 邻邦
+ ============================ -->
+ <a class="hotspot" href="neighbors.html" aria-label="邻邦 — Return to neighboring lands">
+ <title>邻邦 — Neighboring lands</title>
+ <path class="hotspot-shape fill-path" d="M380 500 L420 500 L415 380 L385 380 Z"/>
+ <text class="hotspot-label" x="400" y="470" text-anchor="middle">邻邦</text>
+ </a>
+
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-hosted" class="scene-nav" aria-label="属地导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="https://git.cytrogen.icu">代码库 — Sourcehut</a></li>
+ <li><a class="scene-nav__link" href="https://status.cytrogen.icu">监控塔 — Beszel</a></li>
+ <li><a class="scene-nav__link" href="https://mail.cytrogen.icu">邮局 — Stalwart</a></li>
+ <li><a class="scene-nav__link" href="neighbors.html">邻邦 — 返回街道</a></li>
+ </ul>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/hotel.html => pages/hotel.html +215 -0
@@ 0,0 1,215 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>胶囊旅馆 — Realm</title>
+ <meta name="description" content="胶囊旅馆内部 — Capsule hotel interior">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-hotel">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">胶囊旅馆</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-hotel-title" viewBox="0 0 800 500">
+ <title id="scene-hotel-title">胶囊旅馆内部 — Capsule hotel interior with front desk and capsule rooms</title>
+
+ <!-- Interior wall background -->
+ <rect class="fill-wall-dark" x="0" y="0" width="800" height="500"/>
+
+ <!-- Arched ceiling (capsule dome shape) -->
+ <path class="fill-wall" d="M0 0 L0 100 Q200 30 400 60 Q600 30 800 100 L800 0 Z" aria-hidden="true"/>
+
+ <!-- Floor -->
+ <rect class="fill-ground" x="0" y="400" width="800" height="100"/>
+ <!-- Floor tile lines -->
+ <g class="scene-detail" aria-hidden="true">
+ <rect class="fill-wall-dark" x="0" y="400" width="800" height="2"/>
+ <rect class="fill-path" x="100" y="400" width="2" height="100"/>
+ <rect class="fill-path" x="200" y="400" width="2" height="100"/>
+ <rect class="fill-path" x="300" y="400" width="2" height="100"/>
+ <rect class="fill-path" x="400" y="400" width="2" height="100"/>
+ <rect class="fill-path" x="500" y="400" width="2" height="100"/>
+ <rect class="fill-path" x="600" y="400" width="2" height="100"/>
+ <rect class="fill-path" x="700" y="400" width="2" height="100"/>
+ </g>
+
+ <!-- Wall columns -->
+ <g aria-hidden="true">
+ <!-- Left column -->
+ <rect class="fill-wall" x="0" y="80" width="30" height="320"/>
+ <rect class="fill-wall-light" x="5" y="80" width="5" height="320"/>
+ <!-- Right column -->
+ <rect class="fill-wall" x="770" y="80" width="30" height="320"/>
+ <rect class="fill-wall-light" x="775" y="80" width="5" height="320"/>
+ </g>
+
+ <!-- Wall lamps (decorative) -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left lamp -->
+ <rect class="fill-wall-light" x="40" y="190" width="8" height="20"/>
+ <rect class="fill-accent-shape" x="38" y="182" width="12" height="12"/>
+ <rect class="fill-window-glow" x="30" y="172" width="28" height="14"/>
+ <!-- Right lamp -->
+ <rect class="fill-wall-light" x="752" y="190" width="8" height="20"/>
+ <rect class="fill-accent-shape" x="750" y="182" width="12" height="12"/>
+ <rect class="fill-window-glow" x="742" y="172" width="28" height="14"/>
+ </g>
+
+ <!-- === HOTSPOT: Exit (出口) === -->
+ <a class="hotspot" href="neighbors.html" aria-label="出口 — Return to neighbors">
+ <title>出口 — Return to neighbors</title>
+ <!-- Door frame -->
+ <path class="hotspot-shape" d="M70 400 L70 190 Q70 155 120 145 Q170 155 170 190 L170 400 Z"/>
+ <!-- Door surface -->
+ <rect class="fill-door" x="82" y="200" width="76" height="200"/>
+ <!-- Door handle -->
+ <circle class="fill-accent-shape" cx="145" cy="310" r="4"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="120" y="135" text-anchor="middle">出口</text>
+ </a>
+
+ <!-- === HOTSPOT: Front Desk (前台) === -->
+ <a class="hotspot" href="#desk" aria-label="前台 — Front desk">
+ <title>前台 — Front desk</title>
+ <!-- Counter top -->
+ <rect class="hotspot-shape" x="230" y="300" width="180" height="20"/>
+ <!-- Counter body -->
+ <rect class="hotspot-shape" x="245" y="320" width="150" height="80"/>
+ <!-- Counter front detail -->
+ <rect class="fill-wall-light" x="253" y="330" width="134" height="60"/>
+ <!-- Sign above desk -->
+ <rect class="fill-accent-dim" x="275" y="250" width="90" height="18"/>
+ <!-- Bell on counter -->
+ <path class="fill-accent-shape" d="M310 300 L315 290 L320 300 Z" aria-hidden="true"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="320" y="242" text-anchor="middle">前台</text>
+ </a>
+
+ <!-- === HOTSPOT: Room 101 (top capsule) === -->
+ <g id="room1">
+ <a class="hotspot" href="#room1" aria-label="101号房 — Room 101">
+ <title>101号房 — Room 101</title>
+ <!-- Capsule shell -->
+ <rect class="hotspot-shape" x="530" y="130" width="180" height="70" rx="12"/>
+ <!-- Capsule window -->
+ <rect class="fill-window" x="545" y="148" width="30" height="34"/>
+ <!-- Room number -->
+ <text class="fill-wall-dark" x="680" y="172" text-anchor="middle" font-family="var(--font-mono)" font-size="14">101</text>
+ </a>
+ <!-- Padlock -->
+ <g class="capsule-lock" aria-hidden="true">
+ <!-- Shackle (U-shape) -->
+ <path class="fill-wall-light" d="M615 154 L615 144 Q615 132 625 132 Q635 132 635 144 L635 154"/>
+ <!-- Lock body -->
+ <rect class="fill-wall" x="610" y="154" width="30" height="22" rx="3"/>
+ <!-- Keyhole -->
+ <circle class="fill-door" cx="625" cy="165" r="3"/>
+ </g>
+ <!-- "Not open" text (animated) -->
+ <text class="capsule-lock-text" x="625" y="124" text-anchor="middle">该房间还未开放</text>
+ </g>
+
+ <!-- === HOTSPOT: Room 102 (middle capsule) === -->
+ <g id="room2">
+ <a class="hotspot" href="#room2" aria-label="102号房 — Room 102">
+ <title>102号房 — Room 102</title>
+ <!-- Capsule shell -->
+ <rect class="hotspot-shape" x="530" y="220" width="180" height="70" rx="12"/>
+ <!-- Capsule window -->
+ <rect class="fill-window" x="545" y="238" width="30" height="34"/>
+ <!-- Room number -->
+ <text class="fill-wall-dark" x="680" y="262" text-anchor="middle" font-family="var(--font-mono)" font-size="14">102</text>
+ </a>
+ <!-- Padlock -->
+ <g class="capsule-lock" aria-hidden="true">
+ <!-- Shackle (U-shape) -->
+ <path class="fill-wall-light" d="M615 244 L615 234 Q615 222 625 222 Q635 222 635 234 L635 244"/>
+ <!-- Lock body -->
+ <rect class="fill-wall" x="610" y="244" width="30" height="22" rx="3"/>
+ <!-- Keyhole -->
+ <circle class="fill-door" cx="625" cy="255" r="3"/>
+ </g>
+ <!-- "Not open" text (animated) -->
+ <text class="capsule-lock-text" x="625" y="214" text-anchor="middle">该房间还未开放</text>
+ </g>
+
+ <!-- === HOTSPOT: Room 103 (bottom capsule) === -->
+ <g id="room3">
+ <a class="hotspot" href="#room3" aria-label="103号房 — Room 103">
+ <title>103号房 — Room 103</title>
+ <!-- Capsule shell -->
+ <rect class="hotspot-shape" x="530" y="310" width="180" height="70" rx="12"/>
+ <!-- Capsule window -->
+ <rect class="fill-window" x="545" y="328" width="30" height="34"/>
+ <!-- Room number -->
+ <text class="fill-wall-dark" x="680" y="352" text-anchor="middle" font-family="var(--font-mono)" font-size="14">103</text>
+ </a>
+ <!-- Padlock -->
+ <g class="capsule-lock" aria-hidden="true">
+ <!-- Shackle (U-shape) -->
+ <path class="fill-wall-light" d="M615 334 L615 324 Q615 312 625 312 Q635 312 635 324 L635 334"/>
+ <!-- Lock body -->
+ <rect class="fill-wall" x="610" y="334" width="30" height="22" rx="3"/>
+ <!-- Keyhole -->
+ <circle class="fill-door" cx="625" cy="345" r="3"/>
+ </g>
+ <!-- "Not open" text (animated) -->
+ <text class="capsule-lock-text" x="625" y="304" text-anchor="middle">该房间还未开放</text>
+ </g>
+
+ <!-- Divider between desk area and capsule area -->
+ <rect class="fill-wall" x="460" y="100" width="12" height="300" aria-hidden="true"/>
+ <rect class="fill-wall-light" x="464" y="100" width="4" height="300" aria-hidden="true"/>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-hotel" class="scene-nav" aria-label="胶囊旅馆导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="neighbors.html">出口 — 返回街道</a></li>
+ <li><a class="scene-nav__link" href="#desk">前台 — Gemini 介绍</a></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">101号房(尚未开放)</span></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">102号房(尚未开放)</span></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">103号房(尚未开放)</span></li>
+ </ul>
+ </nav>
+
+ <!-- :target overlay panels -->
+
+ <div id="desk" class="capsule-panel" tabindex="-1">
+ <div class="scroll">
+ <div class="scroll__rod" aria-hidden="true"></div>
+ <div class="scroll__body">
+ <h1 class="scroll__title">前台</h1>
+ <h2>什么是 Gemini</h2>
+ <p>Gemini 是一种轻量级互联网协议,介于 Gopher 的极简和 HTTP 的臃肿之间。</p>
+ <p>它使用专用的 Gemtext 标记语言,只支持标题、列表、引用、链接等基础格式。链接必须独占一行,不能嵌入段落中。</p>
+
+ <h2>为什么推荐</h2>
+ <ul>
+ <li>强制 TLS 加密,无明文传输</li>
+ <li>没有 cookie、没有客户端脚本、没有追踪器、没有广告</li>
+ <li>纯文字体验,让你更贴近内容本身</li>
+ <li>单次请求-响应模型,连接即关闭,简洁高效</li>
+ </ul>
+
+ <h2>如何访问</h2>
+ <p>领主的胶囊地址:<code>gemini://cytrogen.icu</code></p>
+ <p>需要 Gemini 浏览器(如 Lagrange、Kristall)或 Emacs 的 Elpher 插件。</p>
+ </div>
+ <div class="scroll__rod" aria-hidden="true"></div>
+ </div>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ </main>
+
+</body>
+</html>
A pages/interior.html => pages/interior.html +413 -0
@@ 0,0 1,413 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>城堡内部 — Realm</title>
+ <meta name="description" content="城堡内部 — Castle interior with library, workshop, armory, and archive">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-interior">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">城堡内部</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-interior-title" viewBox="0 0 800 500">
+ <title id="scene-interior-title">城堡内部 — Two-story castle interior with perspective view</title>
+
+ <!-- ============================
+ 1. Background
+ ============================ -->
+ <rect class="fill-wall-dark" x="0" y="0" width="800" height="500"/>
+
+ <!-- ============================
+ 2. Merged ceiling + far wall
+ Single polygon eliminates y=50 seam
+ ============================ -->
+ <polygon class="fill-wall" points="0,0 800,0 720,50 720,370 80,370 80,50" aria-hidden="true"/>
+
+ <!-- ============================
+ 3. Far wall decorative lines
+ ============================ -->
+ <!-- Crown molding -->
+ <polygon class="fill-wall-light" points="80,50 720,50 720,56 80,56" aria-hidden="true"/>
+ <!-- Baseboard -->
+ <polygon class="fill-wall-dark" points="80,360 720,360 720,370 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 4. Left side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="0,0 80,50 80,370 0,500" aria-hidden="true"/>
+ <!-- Thin 8px highlight along inner edge -->
+ <polygon class="fill-wall" points="80,50 72,54 72,366 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 5. Right side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="800,0 720,50 720,370 800,500" aria-hidden="true"/>
+ <!-- Thin 8px highlight along inner edge -->
+ <polygon class="fill-wall" points="720,50 728,54 728,366 720,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 6. Ground floor + perspective tile lines
+ ============================ -->
+ <polygon class="fill-ground" points="80,370 720,370 800,500 0,500" aria-hidden="true"/>
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Horizontal lines -->
+ <polygon class="fill-path" points="80,370 720,370 718,372 82,372"/>
+ <polygon class="fill-path" points="56,400 744,400 743,402 57,402"/>
+ <polygon class="fill-path" points="30,430 770,430 769,432 31,432"/>
+ <polygon class="fill-path" points="0,460 800,460 800,462 0,462"/>
+ <!-- Converging vertical lines (toward vanishing point ~400,0) -->
+ <polygon class="fill-path" points="200,370 198,370 140,500 142,500"/>
+ <polygon class="fill-path" points="310,370 308,370 260,500 262,500"/>
+ <polygon class="fill-path" points="400,370 398,370 400,500 398,500"/>
+ <polygon class="fill-path" points="490,370 492,370 540,500 538,500"/>
+ <polygon class="fill-path" points="600,370 602,370 660,500 658,500"/>
+ </g>
+
+ <!-- ============================
+ 7. Sheep painting (far wall upper center)
+ y=78-148, well above mezzanine at y=165
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Frame -->
+ <rect class="fill-wall-dark" x="340" y="78" width="120" height="70"/>
+ <!-- Canvas -->
+ <rect class="fill-board" x="347" y="85" width="106" height="56"/>
+ <!-- Sky in painting -->
+ <rect class="fill-sky" x="347" y="85" width="106" height="28"/>
+ <!-- Ground in painting -->
+ <rect class="fill-ground" x="347" y="113" width="106" height="28"/>
+ <!-- Sheep body -->
+ <polygon class="fill-moon" points="388,107 391,102 405,99 416,102 419,107 419,114 388,114"/>
+ <!-- Sheep head -->
+ <polygon class="fill-moon" points="383,104 388,102 388,109 383,109"/>
+ <!-- Sheep legs -->
+ <rect class="fill-wall-dark" x="392" y="114" width="3" height="6"/>
+ <rect class="fill-wall-dark" x="400" y="114" width="3" height="6"/>
+ <rect class="fill-wall-dark" x="408" y="114" width="3" height="6"/>
+ <rect class="fill-wall-dark" x="414" y="114" width="3" height="6"/>
+ <!-- Sheep eye -->
+ <rect class="fill-wall-dark" x="384" y="105" width="2" height="2"/>
+ </g>
+
+ <!-- ============================
+ 8. Staircase (center, 6 steps)
+ x≈350-450, y=370 → y=220
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Step 1 (bottom, widest) -->
+ <rect class="fill-wall" x="350" y="345" width="100" height="25"/>
+ <rect class="fill-wall-dark" x="350" y="365" width="100" height="5"/>
+ <!-- Step 2 -->
+ <rect class="fill-wall" x="354" y="320" width="92" height="25"/>
+ <rect class="fill-wall-dark" x="354" y="340" width="92" height="5"/>
+ <!-- Step 3 -->
+ <rect class="fill-wall" x="358" y="295" width="84" height="25"/>
+ <rect class="fill-wall-dark" x="358" y="315" width="84" height="5"/>
+ <!-- Step 4 -->
+ <rect class="fill-wall" x="362" y="270" width="76" height="25"/>
+ <rect class="fill-wall-dark" x="362" y="290" width="76" height="5"/>
+ <!-- Step 5 -->
+ <rect class="fill-wall" x="366" y="245" width="68" height="25"/>
+ <rect class="fill-wall-dark" x="366" y="265" width="68" height="5"/>
+ <!-- Step 6 (top, narrowest) -->
+ <rect class="fill-wall" x="370" y="220" width="60" height="25"/>
+ <rect class="fill-wall-dark" x="370" y="240" width="60" height="5"/>
+
+ <!-- Banister pillars at bottom -->
+ <rect class="fill-wall-light" x="345" y="330" width="8" height="40"/>
+ <rect class="fill-wall-light" x="447" y="330" width="8" height="40"/>
+ <!-- Pillar caps -->
+ <rect class="fill-wall-light" x="343" y="326" width="12" height="6"/>
+ <rect class="fill-wall-light" x="445" y="326" width="12" height="6"/>
+ </g>
+
+ <!-- ============================
+ 9. Π-shaped mezzanine (back corridor connects wings)
+ Staircase opening at x=368-432, y=180-200
+ ============================ -->
+ <!-- Π-shaped platform: full-width back, center gap at front -->
+ <polygon class="fill-ground" points="80,165 720,165 720,220 435,220 432,200 368,200 365,220 80,220" aria-hidden="true"/>
+ <!-- Left wing front slab -->
+ <polygon class="fill-wall-dark" points="80,220 365,220 360,232 75,232" aria-hidden="true"/>
+ <!-- Staircase opening upper slab (back corridor underside) -->
+ <polygon class="fill-wall-dark" points="368,200 432,200 434,212 366,212" aria-hidden="true"/>
+ <!-- Right wing front slab -->
+ <polygon class="fill-wall-dark" points="435,220 720,220 725,232 440,232" aria-hidden="true"/>
+
+ <!-- ============================
+ 10. Second-floor locked rooms (3)
+ 3D blocks: top + front + side face, doors on side facing corridor
+ Drawn BEFORE railings so railings appear in front
+ ============================ -->
+
+ <!-- Bedroom 卧室 (left wing, cx=155) -->
+ <g id="room-bedroom">
+ <a class="hotspot" href="about.html" aria-label="卧室 — 关于领主">
+ <title>卧室 — 关于领主</title>
+ <path class="hotspot-shape" d="
+ M135,165 L137,115
+ Q139,98 155,95
+ Q171,98 173,115
+ L175,165 Z
+ "/>
+ <rect class="fill-door" x="140" y="112" width="30" height="53"/>
+ <text class="hotspot-label" x="155" y="88" text-anchor="middle">卧室</text>
+ </a>
+ </g>
+
+ <!-- Ritual room 祭堂 (left wing, cx=285) -->
+ <g id="room-ritual">
+ <a class="hotspot" href="#room-ritual" aria-label="祭堂 — Ritual room (locked)">
+ <title>祭堂 — Ritual room (locked)</title>
+ <path class="hotspot-shape" d="
+ M265,165 L267,115
+ Q269,98 285,95
+ Q301,98 303,115
+ L305,165 Z
+ "/>
+ <rect class="fill-door" x="270" y="112" width="30" height="53"/>
+ </a>
+ <g class="capsule-lock" aria-hidden="true">
+ <path class="fill-wall-light" d="M281 140 L281 135 Q281 130 285 130 Q289 130 289 135 L289 140"/>
+ <rect class="fill-wall" x="278" y="140" width="14" height="10" rx="1"/>
+ <circle class="fill-door" cx="285" cy="144" r="1.5"/>
+ </g>
+ <text class="capsule-lock-text" x="285" y="88" text-anchor="middle">该房间还未开放</text>
+ </g>
+
+ <!-- Unknown room 未知房间 (right wing, cx=515, mirrors 祭堂) -->
+ <g id="room-other">
+ <a class="hotspot" href="#room-other" aria-label="未知房间 — Unknown room (locked)">
+ <title>未知房间 — Unknown room (locked)</title>
+ <path class="hotspot-shape" d="
+ M495,165 L497,115
+ Q499,98 515,95
+ Q531,98 533,115
+ L535,165 Z
+ "/>
+ <rect class="fill-door" x="500" y="112" width="30" height="53"/>
+ </a>
+ <g class="capsule-lock" aria-hidden="true">
+ <path class="fill-wall-light" d="M511 140 L511 135 Q511 130 515 130 Q519 130 519 135 L519 140"/>
+ <rect class="fill-wall" x="508" y="140" width="14" height="10" rx="1"/>
+ <circle class="fill-door" cx="515" cy="144" r="1.5"/>
+ </g>
+ <text class="capsule-lock-text" x="515" y="88" text-anchor="middle">该房间还未开放</text>
+ </g>
+
+ <!-- Unknown room 未知房间 (right wing, cx=645, mirrors 卧室) -->
+ <g id="room-other-2">
+ <a class="hotspot" href="#room-other-2" aria-label="未知房间 — Unknown room (locked)">
+ <title>未知房间 — Unknown room (locked)</title>
+ <path class="hotspot-shape" d="
+ M625,165 L627,115
+ Q629,98 645,95
+ Q661,98 663,115
+ L665,165 Z
+ "/>
+ <rect class="fill-door" x="630" y="112" width="30" height="53"/>
+ </a>
+ <g class="capsule-lock" aria-hidden="true">
+ <path class="fill-wall-light" d="M641 140 L641 135 Q641 130 645 130 Q649 130 649 135 L649 140"/>
+ <rect class="fill-wall" x="638" y="140" width="14" height="10" rx="1"/>
+ <circle class="fill-door" cx="645" cy="144" r="1.5"/>
+ </g>
+ <text class="capsule-lock-text" x="645" y="88" text-anchor="middle">该房间还未开放</text>
+ </g>
+
+ <!-- ============================
+ 11. Balcony railing
+ Left and right segments adapted to platform edges
+ Drawn AFTER rooms so railings appear in front
+ ============================ -->
+ <g aria-hidden="true">
+ <!-- Left railing section -->
+ <rect class="fill-wall-light" x="80" y="175" width="288" height="4"/>
+ <rect class="fill-wall-light" x="75" y="210" width="293" height="4"/>
+ <g class="scene-detail">
+ <rect class="fill-wall" x="90" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="112" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="134" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="156" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="178" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="200" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="222" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="244" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="266" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="288" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="310" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="332" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="354" y="179" width="4" height="31"/>
+ </g>
+
+ <!-- Right railing section -->
+ <rect class="fill-wall-light" x="432" y="175" width="288" height="4"/>
+ <rect class="fill-wall-light" x="432" y="210" width="293" height="4"/>
+ <g class="scene-detail">
+ <rect class="fill-wall" x="445" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="467" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="489" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="511" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="533" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="555" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="577" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="599" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="621" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="643" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="665" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="687" y="179" width="4" height="31"/>
+ <rect class="fill-wall" x="709" y="179" width="4" height="31"/>
+ </g>
+
+ <!-- Tall posts flanking staircase opening -->
+ <rect class="fill-wall-light" x="365" y="168" width="6" height="52"/>
+ <rect class="fill-wall-light" x="429" y="168" width="6" height="52"/>
+ <!-- Post caps -->
+ <rect class="fill-wall-light" x="363" y="164" width="10" height="6"/>
+ <rect class="fill-wall-light" x="427" y="164" width="10" height="6"/>
+ </g>
+
+ <!-- ============================
+ 12. First-floor room doors (4 hotspots)
+ ============================ -->
+
+ <!-- === Library 图书馆 (left 1) === -->
+ <a class="hotspot" href="https://blog.cytrogen.icu" aria-label="图书馆 — Blog">
+ <title>图书馆 — Blog</title>
+ <path class="hotspot-shape" d="
+ M148,370 L155,250
+ Q160,230 190,225
+ Q220,230 225,250
+ L232,370 Z
+ "/>
+ <rect class="fill-door" x="162" y="265" width="56" height="105"/>
+ <!-- Book details -->
+ <rect class="fill-accent-dim" x="155" y="275" width="8" height="30"/>
+ <rect class="fill-window" x="217" y="275" width="8" height="30"/>
+ <rect class="fill-accent-dim" x="155" y="315" width="8" height="25"/>
+ <rect class="fill-window" x="217" y="315" width="8" height="25"/>
+ <!-- Keystone -->
+ <rect class="fill-accent-shape" x="185" y="227" width="10" height="8"/>
+ <text class="hotspot-label" x="190" y="218" text-anchor="middle">图书馆</text>
+ </a>
+
+ <!-- === Workshop 工坊 (left 2) === -->
+ <a class="hotspot" href="colophon.html" aria-label="工坊 — Colophon">
+ <title>工坊 — Colophon</title>
+ <path class="hotspot-shape" d="
+ M262,370 L268,260
+ Q272,242 300,237
+ Q328,242 332,260
+ L338,370 Z
+ "/>
+ <rect class="fill-door" x="276" y="270" width="48" height="100"/>
+ <!-- Iron bands -->
+ <rect class="hotspot-icon" x="276" y="295" width="48" height="4"/>
+ <rect class="hotspot-icon" x="276" y="330" width="48" height="4"/>
+ <!-- Handle -->
+ <circle class="fill-accent-shape" cx="314" cy="315" r="4"/>
+ <!-- Gear icon -->
+ <circle class="hotspot-icon" cx="300" cy="252" r="8"/>
+ <circle class="fill-door" cx="300" cy="252" r="4"/>
+ <text class="hotspot-label" x="300" y="230" text-anchor="middle">工坊</text>
+ </a>
+
+ <!-- === Armory 兵器库 (right 1) === -->
+ <a class="hotspot" href="uses.html" aria-label="兵器库 — Uses">
+ <title>兵器库 — Uses</title>
+ <path class="hotspot-shape" d="
+ M462,370 L468,260
+ Q472,242 500,237
+ Q528,242 532,260
+ L538,370 Z
+ "/>
+ <rect class="fill-door" x="476" y="270" width="48" height="100"/>
+ <!-- Crossed swords -->
+ <polygon class="hotspot-icon" points="490,278 493,278 504,350 501,350"/>
+ <polygon class="hotspot-icon" points="510,278 507,278 496,350 499,350"/>
+ <!-- Shield -->
+ <path class="hotspot-icon" d="M494,300 L500,294 L506,300 L500,315 Z"/>
+ <text class="hotspot-label" x="500" y="230" text-anchor="middle">兵器库</text>
+ </a>
+
+ <!-- === Archive 典籍室 (right 2) === -->
+ <a class="hotspot" href="canon.html" aria-label="典籍室 — Canon">
+ <title>典籍室 — Canon</title>
+ <path class="hotspot-shape" d="
+ M570,370 L575,260
+ Q578,242 605,237
+ Q632,242 635,260
+ L640,370 Z
+ "/>
+ <rect class="fill-door" x="582" y="270" width="46" height="100"/>
+ <!-- Scroll lines -->
+ <rect class="hotspot-icon" x="590" y="290" width="30" height="5"/>
+ <rect class="hotspot-icon" x="590" y="302" width="30" height="5"/>
+ <rect class="hotspot-icon" x="590" y="314" width="26" height="5"/>
+ <!-- Keystone -->
+ <rect class="fill-accent-shape" x="600" y="239" width="10" height="6"/>
+ <text class="hotspot-label" x="605" y="230" text-anchor="middle">典籍室</text>
+ </a>
+
+ <!-- ============================
+ 13. Torch sconces (decorative)
+ ============================ -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left side wall torch (1F) -->
+ <rect class="fill-wall-light" x="80" y="290" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="78" y="282" width="10" height="10"/>
+ <rect class="fill-window-glow" x="73" y="274" width="20" height="12"/>
+
+ <!-- Right side wall torch (1F) -->
+ <rect class="fill-wall-light" x="714" y="290" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="712" y="282" width="10" height="10"/>
+ <rect class="fill-window-glow" x="707" y="274" width="20" height="12"/>
+
+ <!-- Left balcony torch (2F, between rooms, cx=220) -->
+ <rect class="fill-wall-light" x="218" y="115" width="5" height="14"/>
+ <rect class="fill-accent-shape" x="216" y="108" width="9" height="9"/>
+ <rect class="fill-window-glow" x="212" y="102" width="17" height="10"/>
+
+ <!-- Right balcony torch (2F, between rooms, cx=580) -->
+ <rect class="fill-wall-light" x="578" y="115" width="5" height="14"/>
+ <rect class="fill-accent-shape" x="576" y="108" width="9" height="9"/>
+ <rect class="fill-window-glow" x="572" y="102" width="17" height="10"/>
+ </g>
+
+ <!-- ============================
+ 14. Return button
+ ============================ -->
+ <a class="hotspot" href="castle.html" aria-label="城门 — Return to castle exterior">
+ <title>城门 — Return to castle exterior</title>
+ <rect class="hotspot-shape" x="350" y="450" width="100" height="45" rx="4"/>
+ <text class="hotspot-label" x="400" y="478" text-anchor="middle">城门</text>
+ </a>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-interior" class="scene-nav" aria-label="城堡内部导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="https://blog.cytrogen.icu">图书馆 — 博客</a></li>
+ <li><a class="scene-nav__link" href="colophon.html">工坊 — 站点构成</a></li>
+ <li><a class="scene-nav__link" href="uses.html">兵器库 — 装备</a></li>
+ <li><a class="scene-nav__link" href="canon.html">典籍室 — 书籍与灵感</a></li>
+ <li><a class="scene-nav__link" href="about.html">卧室 — 关于领主</a></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">祭堂(尚未开放)</span></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">未知房间(尚未开放)</span></li>
+ <li><span class="scene-nav__link scene-nav__link--locked">未知房间(尚未开放)</span></li>
+ <li><a class="scene-nav__link" href="castle.html">城门 — 返回城堡外观</a></li>
+ </ul>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/map.html => pages/map.html +213 -0
@@ 0,0 1,213 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>领地总览 — Realm</title>
+ <meta name="description" content="领地总览 — Bird's-eye overview of the entire Realm territory">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-map">跳过场景</a>
+
+ <main class="realm-scene" style="--scene-bg: oklch(0.12 0.03 290); --scene-max-width: none">
+ <h1 class="visually-hidden">领地总览</h1>
+
+ <div class="realm-scene__content">
+ <div class="realm-scene__backdrop">
+
+ <svg role="group" aria-labelledby="scene-map-title" viewBox="0 0 800 500">
+ <title id="scene-map-title">领地总览 — Map board showing neighbors, castle, and interior zones</title>
+
+ <!-- Background -->
+ <rect class="fill-sky" x="0" y="0" width="800" height="500"/>
+
+ <!-- Board frame -->
+ <rect class="fill-wall-dark" x="30" y="15" width="740" height="470"/>
+
+ <!-- Board surface -->
+ <rect class="fill-board" x="45" y="30" width="710" height="440"/>
+
+ <!-- ============================================================
+ ZONE FILLS (non-interactive backgrounds)
+ ============================================================ -->
+
+ <!-- Neighbors zone -->
+ <rect class="fill-mountain" x="60" y="75" width="170" height="330"/>
+
+ <!-- Castle zone -->
+ <rect class="fill-wall" x="250" y="75" width="490" height="330"/>
+
+ <!-- Interior zone (nested in castle) -->
+ <rect class="fill-mountain-far" x="280" y="165" width="435" height="150"/>
+
+ <!-- ============================================================
+ ZONE HEADERS (clickable bands → zone scene pages)
+ ============================================================ -->
+
+ <!-- Zone header: 邻邦 -->
+ <a class="hotspot" href="neighbors.html" aria-label="邻邦 — Neighboring lands">
+ <title>邻邦 — Neighboring lands</title>
+ <rect class="hotspot-shape" x="60" y="75" width="170" height="25"/>
+ <text class="scene-title" x="145" y="94" text-anchor="middle">邻 邦</text>
+ </a>
+
+ <!-- Zone header: 城堡 -->
+ <a class="hotspot" href="castle.html" aria-label="城堡 — Castle">
+ <title>城堡 — Castle</title>
+ <rect class="hotspot-shape" x="250" y="75" width="490" height="25"/>
+ <text class="scene-title" x="495" y="94" text-anchor="middle">城 堡</text>
+ </a>
+
+ <!-- Zone header: 内部 -->
+ <a class="hotspot" href="interior.html" aria-label="城堡内部 — Castle interior">
+ <title>城堡内部 — Castle interior</title>
+ <rect class="hotspot-shape" x="280" y="165" width="435" height="24"/>
+ <text class="scene-title" x="497" y="183" text-anchor="middle">内 部</text>
+ </a>
+
+ <!-- ============================================================
+ NEIGHBORS SUB-HOTSPOTS (dot markers)
+ ============================================================ -->
+
+ <!-- 友邻 (Friends) -->
+ <a class="hotspot" href="friends.html" aria-label="友邻 — Friends">
+ <title>友邻 — Friends</title>
+ <circle class="fill-accent-dim" cx="95" cy="145" r="4"/>
+ <text class="map-label" x="109" y="149">友邻</text>
+ </a>
+
+ <!-- 属地 (Hosted) -->
+ <a class="hotspot" href="hosted.html" aria-label="属地 — Hosted services">
+ <title>属地 — Hosted</title>
+ <circle class="fill-accent-dim" cx="95" cy="215" r="4"/>
+ <text class="map-label" x="109" y="219">属地</text>
+ </a>
+
+ <!-- 旅馆 (Hotel / Gemini) -->
+ <a class="hotspot" href="hotel.html" aria-label="胶囊旅馆 — Gemini protocol">
+ <title>胶囊旅馆 — Gemini</title>
+ <circle class="fill-accent-dim" cx="95" cy="290" r="4"/>
+ <text class="map-label" x="109" y="294">旅馆</text>
+ </a>
+
+ <!-- 驿站 (Station) -->
+ <a class="hotspot" href="station.html" aria-label="驿站 — Relay station">
+ <title>驿站 — Relay station</title>
+ <circle class="fill-accent-dim" cx="95" cy="365" r="4"/>
+ <text class="map-label" x="109" y="369">驿站</text>
+ </a>
+
+ <!-- ============================================================
+ INTERIOR SUB-HOTSPOTS (2x2 grid inside castle)
+ ============================================================ -->
+
+ <!-- 图书馆 (Blog / Library) — external link -->
+ <a class="hotspot" href="https://blog.cytrogen.icu" aria-label="图书馆 — Blog">
+ <title>图书馆 — Blog</title>
+ <circle class="fill-accent-dim" cx="370" cy="225" r="4"/>
+ <text class="map-label" x="384" y="229">图书馆</text>
+ </a>
+
+ <!-- 工坊 (Colophon / Workshop) -->
+ <a class="hotspot" href="colophon.html" aria-label="工坊 — Colophon">
+ <title>工坊 — Colophon</title>
+ <circle class="fill-accent-dim" cx="580" cy="225" r="4"/>
+ <text class="map-label" x="594" y="229">工坊</text>
+ </a>
+
+ <!-- 兵器库 (Uses / Armory) -->
+ <a class="hotspot" href="uses.html" aria-label="兵器库 — Uses">
+ <title>兵器库 — Uses</title>
+ <circle class="fill-accent-dim" cx="370" cy="280" r="4"/>
+ <text class="map-label" x="384" y="284">兵器库</text>
+ </a>
+
+ <!-- 典籍室 (Canon / Archive) -->
+ <a class="hotspot" href="canon.html" aria-label="典籍室 — Canon">
+ <title>典籍室 — Canon</title>
+ <circle class="fill-accent-dim" cx="580" cy="280" r="4"/>
+ <text class="map-label" x="594" y="284">典籍室</text>
+ </a>
+
+ <!-- ============================================================
+ CASTLE SUB-HOTSPOTS (below interior zone)
+ ============================================================ -->
+
+ <!-- 联络处 (Contact) -->
+ <a class="hotspot" href="contact.html" aria-label="联络处 — Contact">
+ <title>联络处 — Contact</title>
+ <circle class="fill-accent-dim" cx="345" cy="355" r="4"/>
+ <text class="map-label" x="359" y="359">联络处</text>
+ </a>
+
+ <!-- 公告 (Announcement) -->
+ <a class="hotspot" href="announcement.html" aria-label="领地公告 — Announcement">
+ <title>领地公告 — Announcement</title>
+ <circle class="fill-accent-dim" cx="497" cy="355" r="4"/>
+ <text class="map-label" x="511" y="359">公告</text>
+ </a>
+
+ <!-- 遗言 (Death) -->
+ <a class="hotspot" href="death.html" aria-label="遗言 — Death">
+ <title>遗言 — Death</title>
+ <circle class="fill-accent-dim" cx="640" cy="355" r="4"/>
+ <text class="map-label" x="654" y="359">遗言</text>
+ </a>
+
+ <!-- ============================================================
+ DECORATIVE + NAVIGATION
+ ============================================================ -->
+
+ <!-- Compass rose (bottom-right of board) -->
+ <g class="scene-detail" aria-hidden="true" transform="translate(710,445)">
+ <polygon class="fill-wall-light" points="0,-16 4,-4 0,-6 -4,-4"/>
+ <polygon class="fill-wall" points="0,16 4,4 0,6 -4,4"/>
+ <polygon class="fill-wall" points="-16,0 -4,-4 -6,0 -4,4"/>
+ <polygon class="fill-wall" points="16,0 4,-4 6,0 4,4"/>
+ <circle class="fill-accent-shape" cx="0" cy="0" r="2"/>
+ </g>
+
+ <!-- Return hotspot (bottom-left of board) -->
+ <a class="hotspot" href="neighbors.html" aria-label="返回邻邦 — Return to neighbors">
+ <title>返回 — Return to neighbors</title>
+ <rect class="hotspot-shape" x="55" y="432" width="65" height="22"/>
+ <text class="scene-title" x="87" y="448" text-anchor="middle">◁ 返回</text>
+ </a>
+
+ <!-- Scene title (rendered last to stay on top) -->
+ <text class="scene-title" x="400" y="58" text-anchor="middle">领 地 总 览</text>
+ </svg>
+
+ </div>
+ </div>
+
+ <nav id="scene-nav-map" class="scene-nav" aria-label="领地总览导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="neighbors.html">邻邦 — 邻近区域</a></li>
+ <li><a class="scene-nav__link" href="castle.html">城堡 — 城堡外观</a></li>
+ <li><a class="scene-nav__link" href="interior.html">城堡内部 — 城堡内部</a></li>
+ <li><a class="scene-nav__link" href="friends.html">友邻 — 友人</a></li>
+ <li><a class="scene-nav__link" href="hosted.html">属地 — 自托管服务</a></li>
+ <li><a class="scene-nav__link" href="hotel.html">胶囊旅馆 — Gemini</a></li>
+ <li><a class="scene-nav__link" href="station.html">驿站 — 中转站</a></li>
+ <li><a class="scene-nav__link" href="https://blog.cytrogen.icu">图书馆 — 博客</a></li>
+ <li><a class="scene-nav__link" href="colophon.html">工坊 — 站点构成</a></li>
+ <li><a class="scene-nav__link" href="uses.html">兵器库 — 装备</a></li>
+ <li><a class="scene-nav__link" href="canon.html">典籍室 — 书籍与灵感</a></li>
+ <li><a class="scene-nav__link" href="contact.html">联络处 — 联系方式</a></li>
+ <li><a class="scene-nav__link" href="announcement.html">公告 — 领地公告</a></li>
+ <li><a class="scene-nav__link" href="death.html">遗言 — 墓志铭</a></li>
+ <li><a class="scene-nav__link" href="neighbors.html">返回邻邦</a></li>
+ </ul>
+ </nav>
+
+ <nav class="realm-scene__nav realm-nav">
+ <a href="neighbors.html">← 返回邻邦</a>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/neighbors.html => pages/neighbors.html +189 -0
@@ 0,0 1,189 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>邻邦 — Realm</title>
+ <meta name="description" content="邻邦 — Neighboring lands of cytrogen.icu">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-neighbors">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">邻邦</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-neighbors-title" viewBox="0 0 800 500">
+ <title id="scene-neighbors-title">邻邦 — Neighboring lands with friends pavilion, map board, estates, capsule inn, and relay station</title>
+
+ <!-- Sky -->
+ <rect class="fill-sky" x="0" y="0" width="800" height="500"/>
+
+ <!-- Stars -->
+ <g class="scene-detail" aria-hidden="true">
+ <rect class="fill-star" x="100" y="40" width="2" height="2"/>
+ <rect class="fill-star" x="300" y="25" width="3" height="3"/>
+ <rect class="fill-star" x="500" y="50" width="2" height="2"/>
+ <rect class="fill-star" x="700" y="35" width="2" height="2"/>
+ <rect class="fill-star" x="420" y="15" width="3" height="3"/>
+ </g>
+
+ <!-- Distant hills -->
+ <path class="fill-mountain-far" d="M0 300 L120 230 L250 270 L400 200 L550 260 L700 220 L800 260 L800 340 L0 340 Z" aria-hidden="true"/>
+
+ <!-- Ground -->
+ <rect class="fill-ground" x="0" y="310" width="800" height="190"/>
+
+ <!-- Road from castle (left side, going right) -->
+ <path class="fill-path" d="M0 400 L0 370 L800 350 L800 380 Z" aria-hidden="true"/>
+ <path class="fill-path" d="M0 420 L0 440 L100 435 L100 418 Z" aria-hidden="true"/>
+
+ <!-- === HOTSPOT: Friends Hill (友邻) === -->
+ <a class="hotspot" href="friends.html" aria-label="友邻 — Friends">
+ <title>友邻 — Friends</title>
+ <!-- Hill -->
+ <path class="fill-mountain" d="M80 310 Q110 240 160 230 Q210 240 240 310 Z"/>
+ <!-- Houses on hilltop -->
+ <rect class="hotspot-shape" x="120" y="255" width="22" height="18"/>
+ <rect class="hotspot-shape" x="148" y="250" width="18" height="23"/>
+ <rect class="hotspot-shape" x="170" y="258" width="20" height="15"/>
+ <rect class="hotspot-shape" x="135" y="240" width="15" height="18"/>
+ <rect class="hotspot-shape" x="160" y="243" width="12" height="17"/>
+ <!-- Rooftops -->
+ <polygon class="hotspot-shape" points="118,255 131,243 144,255"/>
+ <polygon class="hotspot-shape" points="146,250 157,238 168,250"/>
+ <polygon class="hotspot-shape" points="168,258 180,248 192,258"/>
+ <!-- Tiny windows -->
+ <rect class="fill-window" x="127" y="262" width="5" height="5"/>
+ <rect class="fill-window" x="153" y="257" width="4" height="5"/>
+ <rect class="fill-window" x="177" y="263" width="5" height="4"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="160" y="225" text-anchor="middle">友邻</text>
+ </a>
+
+ <!-- === HOTSPOT: Map Board (地图 / Map) === -->
+ <a class="hotspot" href="map.html" aria-label="地图 — Map overview">
+ <title>地图 — Map overview</title>
+ <!-- Post -->
+ <rect class="hotspot-icon" x="328" y="320" width="8" height="35"/>
+ <!-- Board face -->
+ <rect class="hotspot-shape" x="296" y="263" width="72" height="55"/>
+ <!-- Bracket nubs at top corners -->
+ <rect class="hotspot-icon" x="293" y="263" width="5" height="8"/>
+ <rect class="hotspot-icon" x="366" y="263" width="5" height="8"/>
+ <!-- Inner frame border -->
+ <rect class="hotspot-icon" x="302" y="269" width="60" height="43"/>
+ <!-- Board surface (visible inside frame) -->
+ <rect class="hotspot-shape" x="304" y="271" width="56" height="39"/>
+ <!-- Grid divider lines (2×2 territory grid) -->
+ <rect class="fill-wall-dark" x="331" y="271" width="2" height="39"/>
+ <rect class="fill-wall-dark" x="304" y="289" width="56" height="2"/>
+ <!-- Zone markers -->
+ <rect class="fill-wall" x="310" y="276" width="16" height="9"/>
+ <rect class="fill-wall-light" x="338" y="276" width="16" height="9"/>
+ <rect class="fill-accent-dim" x="310" y="296" width="16" height="9"/>
+ <rect class="fill-wall" x="338" y="296" width="16" height="9"/>
+ <!-- "You are here" dot in neighbors quadrant -->
+ <circle class="fill-accent-shape" cx="318" cy="300" r="2"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="332" y="256" text-anchor="middle">地图</text>
+ </a>
+
+ <!-- === HOTSPOT: Walled Manor (属地 / Hosted) === -->
+ <a class="hotspot" href="hosted.html" aria-label="属地 — Hosted services">
+ <title>属地 — Hosted</title>
+ <!-- Perimeter wall -->
+ <rect class="hotspot-shape" x="465" y="280" width="120" height="35"/>
+ <!-- Battlements -->
+ <path class="hotspot-shape" d="
+ M465 280 L465 273 L478 273 L478 268 L491 268 L491 273
+ L504 273 L504 268 L517 268 L517 273 L530 273 L530 268
+ L543 268 L543 273 L556 273 L556 268 L569 268 L569 273
+ L585 273 L585 280 Z
+ "/>
+ <!-- Monitoring tower poking above wall -->
+ <rect class="hotspot-shape" x="540" y="248" width="22" height="32"/>
+ <polygon class="hotspot-shape" points="537,248 551,230 565,248"/>
+ <!-- Tower signal beacon -->
+ <circle class="fill-accent-shape" cx="551" cy="237" r="3"/>
+ <!-- Tower window -->
+ <rect class="fill-window" x="546" y="258" width="8" height="10"/>
+ <!-- Gate opening -->
+ <rect class="fill-door" x="500" y="300" width="16" height="15"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="525" y="223" text-anchor="middle">属地</text>
+ </a>
+
+ <!-- === HOTSPOT: Capsule Inn (胶囊旅馆 / Gemini) === -->
+ <a class="hotspot" href="hotel.html" aria-label="胶囊旅馆 — Gemini protocol">
+ <title>胶囊旅馆 — Gemini</title>
+ <!-- Capsule shape -->
+ <path class="hotspot-shape" d="
+ M650 310 L650 280
+ Q650 260 670 260
+ Q690 260 690 280
+ L690 310 Z
+ "/>
+ <!-- Capsule window -->
+ <rect class="fill-window" x="663" y="272" width="14" height="10"/>
+ <!-- Capsule door -->
+ <rect class="fill-door" x="660" y="290" width="20" height="20"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="670" y="253" text-anchor="middle">旅馆</text>
+ </a>
+
+ <!-- === HOTSPOT: Relay Station (驿站 / RSS) === -->
+ <a class="hotspot" href="station.html" aria-label="驿站 — Relay station">
+ <title>驿站 — Relay station</title>
+ <!-- Station building -->
+ <rect class="hotspot-shape" x="730" y="280" width="55" height="40"/>
+ <!-- Peaked roof -->
+ <polygon class="hotspot-shape" points="725,280 758,255 790,280"/>
+ <!-- Flag pole -->
+ <rect class="hotspot-icon" x="770" y="245" width="3" height="35"/>
+ <!-- Flag -->
+ <polygon class="fill-accent-shape" points="773,248 795,255 773,262"/>
+ <!-- Window -->
+ <rect class="fill-window" x="745" y="290" width="12" height="12"/>
+ <!-- Door -->
+ <rect class="fill-door" x="762" y="298" width="12" height="22"/>
+ <!-- Label -->
+ <text class="hotspot-label" x="758" y="248" text-anchor="middle">驿站</text>
+ </a>
+
+ <!-- Decorative trees -->
+ <g class="scene-detail" aria-hidden="true">
+ <polygon class="fill-tree" points="40,330 55,280 70,330"/>
+ <polygon class="fill-tree" points="35,350 55,310 75,350"/>
+ <polygon class="fill-tree" points="240,325 255,275 270,325"/>
+ <polygon class="fill-tree" points="620,330 635,290 650,330"/>
+ </g>
+
+ <!-- === HOTSPOT: Road back to castle === -->
+ <a class="hotspot" href="castle.html" aria-label="城堡 — Return to castle">
+ <title>城堡 — Return to castle</title>
+ <path class="hotspot-shape fill-path" d="M310 500 L355 500 L345 355 L320 355 Z"/>
+ <text class="hotspot-label" x="332" y="480" text-anchor="middle">城堡</text>
+ </a>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-neighbors" class="scene-nav" aria-label="邻邦导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="friends.html">友邻 — 友人</a></li>
+ <li><a class="scene-nav__link" href="map.html">地图 — 领地总览</a></li>
+ <li><a class="scene-nav__link" href="hosted.html">属地 — 自托管服务</a></li>
+ <li><a class="scene-nav__link" href="hotel.html">胶囊旅馆 — Gemini</a></li>
+ <li><a class="scene-nav__link" href="station.html">驿站 — 中转站</a></li>
+ <li><a class="scene-nav__link" href="castle.html">城堡 — 返回城堡</a></li>
+ </ul>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/station.html => pages/station.html +60 -0
@@ 0,0 1,60 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>驿站 — Realm</title>
+ <meta name="description" content="驿站 — Relay station of the Realm">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#content">跳过场景</a>
+
+ <main class="realm-scene" style="--scene-bg: oklch(0.25 0.04 278)">
+ <h1 class="visually-hidden">驿站</h1>
+ <div class="realm-scene__content">
+ <div class="realm-scene__backdrop">
+ <svg role="img" aria-labelledby="station-title" viewBox="0 0 400 380">
+ <title id="station-title">驿站 — 驿站正门</title>
+
+ <!-- Wall background (close-up view) -->
+ <rect class="fill-wall" x="0" y="0" width="400" height="380"/>
+
+ <!-- Ground -->
+ <rect class="fill-ground" x="0" y="330" width="400" height="50"/>
+
+ <!-- Door frame -->
+ <rect class="fill-wall-light" x="100" y="80" width="200" height="240"/>
+
+ <!-- Door panel -->
+ <rect class="fill-door" x="110" y="88" width="180" height="232"/>
+
+ <!-- Notice board on door -->
+ <rect class="fill-wall-light" x="150" y="140" width="100" height="50" rx="3"/>
+ <text fill="var(--text-dim)" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14">
+ <tspan x="200" y="161">驿站还未开放</tspan>
+ <tspan x="200" y="177" font-size="10">Not Yet Open</tspan>
+ </text>
+
+ <!-- Door handle -->
+ <circle class="fill-wall-light" cx="260" cy="240" r="6"/>
+
+ <!-- Front steps -->
+ <g class="scene-detail" aria-hidden="true">
+ <rect class="fill-path" x="90" y="320" width="220" height="14"/>
+ <rect class="fill-path" x="78" y="334" width="244" height="14"/>
+ <rect class="fill-path" x="66" y="348" width="268" height="14"/>
+ </g>
+ </svg>
+ </div>
+ </div>
+
+ <nav id="content" class="realm-scene__nav realm-nav">
+ <a href="neighbors.html">← 返回街道</a>
+ </nav>
+ </main>
+
+</body>
+</html>
A pages/uses.html => pages/uses.html +925 -0
@@ 0,0 1,925 @@
+<!DOCTYPE html>
+<html lang="zh-Hans">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>兵器库 — Realm</title>
+ <meta name="description" content="兵器库 — Armory of the Realm lord's hardware, software, communications, services, and accessories">
+ <meta name="theme-color" content="#1a1a2e">
+ <link rel="stylesheet" href="../css/realm.css">
+</head>
+<body>
+
+ <a class="skip-link" href="#scene-nav-armory">跳过场景</a>
+
+ <main class="realm-folder">
+ <h1 class="visually-hidden">兵器库</h1>
+
+ <div class="folder-content">
+
+ <svg role="group" aria-labelledby="scene-armory-title" viewBox="0 0 800 500">
+ <title id="scene-armory-title">兵器库 — Stone chamber displaying weapons, artifacts, scrolls, and treasures</title>
+
+ <!-- ============================
+ 1. Background
+ ============================ -->
+ <rect class="fill-wall-dark" x="0" y="0" width="800" height="500"/>
+
+ <!-- ============================
+ 2. Far wall + crown molding + baseboard
+ ============================ -->
+ <polygon class="fill-wall" points="0,0 800,0 720,50 720,370 80,370 80,50" aria-hidden="true"/>
+ <polygon class="fill-wall-light" points="80,50 720,50 720,56 80,56" aria-hidden="true"/>
+ <polygon class="fill-wall-dark" points="80,360 720,360 720,370 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 3. Left side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="0,0 80,50 80,370 0,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="80,50 72,54 72,366 80,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 4. Right side wall + highlight strip
+ ============================ -->
+ <polygon class="fill-wall-dark" points="800,0 720,50 720,370 800,500" aria-hidden="true"/>
+ <polygon class="fill-wall" points="720,50 728,54 728,366 720,370" aria-hidden="true"/>
+
+ <!-- ============================
+ 5. Ground floor + perspective grid
+ ============================ -->
+ <polygon class="fill-ground" points="80,370 720,370 800,500 0,500" aria-hidden="true"/>
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Horizontal lines -->
+ <polygon class="fill-path" points="80,370 720,370 718,372 82,372"/>
+ <polygon class="fill-path" points="56,400 744,400 743,402 57,402"/>
+ <polygon class="fill-path" points="30,430 770,430 769,432 31,432"/>
+ <polygon class="fill-path" points="0,460 800,460 800,462 0,462"/>
+ <!-- Converging vertical lines -->
+ <polygon class="fill-path" points="200,370 198,370 140,500 142,500"/>
+ <polygon class="fill-path" points="310,370 308,370 260,500 262,500"/>
+ <polygon class="fill-path" points="400,370 398,370 400,500 398,500"/>
+ <polygon class="fill-path" points="490,370 492,370 540,500 538,500"/>
+ <polygon class="fill-path" points="600,370 602,370 660,500 658,500"/>
+ </g>
+
+ <!-- ============================
+ 6. Decorative torches
+ ============================ -->
+ <g class="scene-detail" aria-hidden="true">
+ <!-- Left wall torch -->
+ <rect class="fill-wall-light" x="82" y="250" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="80" y="242" width="10" height="10"/>
+ <rect class="fill-window-glow" x="75" y="234" width="20" height="12"/>
+ <!-- Right wall torch -->
+ <rect class="fill-wall-light" x="712" y="250" width="6" height="18"/>
+ <rect class="fill-accent-shape" x="710" y="242" width="10" height="10"/>
+ <rect class="fill-window-glow" x="705" y="234" width="20" height="12"/>
+ </g>
+
+ <!-- ============================
+ 7. Hotspot: 铁甲架 (Armor rack → Hardware)
+ Left wall area
+ ============================ -->
+ <a class="hotspot" href="#panel-hardware" aria-label="铁甲 — Hardware">
+ <title>铁甲 — Hardware</title>
+ <rect class="hotspot-shape" x="100" y="78" width="130" height="220"/>
+ <!-- Stand pole -->
+ <rect class="fill-wall-light" x="160" y="90" width="10" height="200"/>
+ <!-- Cross bar (shoulders) -->
+ <rect class="fill-wall-light" x="118" y="98" width="94" height="8"/>
+ <!-- Helmet on top -->
+ <rect class="fill-door" x="145" y="80" width="40" height="22" rx="4"/>
+ <!-- Shoulder pads -->
+ <rect class="fill-door" x="112" y="106" width="36" height="16"/>
+ <rect class="fill-door" x="182" y="106" width="36" height="16"/>
+ <!-- Breastplate -->
+ <rect class="fill-door" x="130" y="122" width="70" height="60"/>
+ <!-- Belt -->
+ <rect class="fill-wall" x="130" y="176" width="70" height="6"/>
+ <!-- Crossed swords behind stand -->
+ <polygon class="fill-wall" points="110,286 114,286 165,100 161,100"/>
+ <polygon class="fill-wall" points="220,286 216,286 165,100 169,100"/>
+ <text class="hotspot-label" x="165" y="72" text-anchor="middle">铁甲</text>
+ </a>
+
+ <!-- ============================
+ 8. Hotspot: 法器柜 (Magic cabinet → Software)
+ Far wall left half
+ ============================ -->
+ <a class="hotspot" href="#panel-software" aria-label="法器 — Software">
+ <title>法器 — Software</title>
+ <rect class="hotspot-shape" x="260" y="72" width="120" height="180"/>
+ <!-- Cabinet body -->
+ <rect class="fill-wall-dark" x="268" y="80" width="104" height="164"/>
+ <!-- Top trim -->
+ <rect class="fill-wall-light" x="264" y="76" width="112" height="6"/>
+ <!-- Cabinet doors -->
+ <rect class="fill-door" x="272" y="86" width="46" height="76"/>
+ <rect class="fill-door" x="322" y="86" width="46" height="76"/>
+ <!-- Door handles -->
+ <rect class="fill-accent-dim" x="310" y="118" width="4" height="12"/>
+ <rect class="fill-accent-dim" x="326" y="118" width="4" height="12"/>
+ <!-- Bottom shelf -->
+ <rect class="fill-wall" x="272" y="168" width="96" height="4"/>
+ <!-- Objects on shelf -->
+ <rect class="fill-door" x="282" y="176" width="16" height="24"/>
+ <rect class="fill-door" x="308" y="180" width="12" height="20"/>
+ <rect class="fill-door" x="332" y="174" width="20" height="26"/>
+ <!-- Glow from inside doors -->
+ <rect class="fill-window-glow" x="278" y="92" width="34" height="64"/>
+ <rect class="fill-window-glow" x="328" y="92" width="34" height="64"/>
+ <text class="hotspot-label" x="320" y="66" text-anchor="middle">法器</text>
+ </a>
+
+ <!-- ============================
+ 9. Hotspot: 信鸽笼 (Pigeon cage → Communications)
+ Far wall right half
+ ============================ -->
+ <a class="hotspot" href="#panel-comms" aria-label="信物 — Communications">
+ <title>信物 — Communications</title>
+ <rect class="hotspot-shape" x="480" y="72" width="120" height="165"/>
+ <!-- Hanging chain -->
+ <rect class="fill-wall" x="538" y="56" width="4" height="24"/>
+ <!-- Cage top bar -->
+ <rect class="fill-wall-light" x="492" y="80" width="96" height="6"/>
+ <!-- Vertical bars -->
+ <rect class="fill-wall-light" x="500" y="86" width="4" height="136"/>
+ <rect class="fill-wall-light" x="520" y="86" width="4" height="136"/>
+ <rect class="fill-wall-light" x="540" y="86" width="4" height="136"/>
+ <rect class="fill-wall-light" x="560" y="86" width="4" height="136"/>
+ <rect class="fill-wall-light" x="580" y="86" width="4" height="136"/>
+ <!-- Cage bottom bar -->
+ <rect class="fill-wall-light" x="492" y="222" width="96" height="6"/>
+ <!-- Bird silhouettes -->
+ <rect class="fill-door" x="508" y="198" width="10" height="8"/>
+ <rect class="fill-door" x="506" y="194" width="6" height="6"/>
+ <rect class="fill-door" x="548" y="202" width="10" height="8"/>
+ <rect class="fill-door" x="546" y="198" width="6" height="6"/>
+ <text class="hotspot-label" x="540" y="70" text-anchor="middle">信物</text>
+ </a>
+
+ <!-- ============================
+ 10. Hotspot: 契书台 (Scroll desk → Services)
+ Right wall area
+ ============================ -->
+ <a class="hotspot" href="#panel-services" aria-label="契约 — Services">
+ <title>契约 — Services</title>
+ <rect class="hotspot-shape" x="618" y="100" width="100" height="200"/>
+ <!-- Desk surface -->
+ <rect class="fill-wall-light" x="622" y="200" width="92" height="8"/>
+ <!-- Desk body -->
+ <rect class="fill-wall" x="626" y="208" width="84" height="80"/>
+ <!-- Desk legs -->
+ <rect class="fill-wall-dark" x="630" y="288" width="10" height="10"/>
+ <rect class="fill-wall-dark" x="696" y="288" width="10" height="10"/>
+ <!-- Scrolls on desk -->
+ <rect class="fill-door" x="634" y="130" width="22" height="66" rx="4"/>
+ <rect class="fill-door" x="664" y="118" width="22" height="78" rx="4"/>
+ <rect class="fill-door" x="694" y="140" width="18" height="56" rx="4"/>
+ <!-- Wax seal on scroll -->
+ <circle class="fill-accent-dim" cx="675" cy="164" r="5"/>
+ <text class="hotspot-label" x="668" y="96" text-anchor="middle">契约</text>
+ </a>
+
+ <!-- ============================
+ 11. Hotspot: 佩饰匣 (Accessory box → Other)
+ Ground left
+ ============================ -->
+ <a class="hotspot" href="#panel-other" aria-label="佩饰 — Other">
+ <title>佩饰 — Other</title>
+ <rect class="hotspot-shape" x="280" y="380" width="130" height="80"/>
+ <!-- Box body -->
+ <rect class="fill-wall" x="290" y="400" width="110" height="50"/>
+ <!-- Open lid -->
+ <polygon class="fill-wall-light" points="290,400 400,400 390,380 300,380"/>
+ <!-- Items visible inside -->
+ <rect class="fill-accent-dim" x="305" y="418" width="14" height="14"/>
+ <rect class="fill-door" x="330" y="416" width="18" height="16"/>
+ <circle class="fill-accent-dim" cx="370" cy="426" r="8"/>
+ <text class="hotspot-label" x="345" y="374" text-anchor="middle">佩饰</text>
+ </a>
+
+ <!-- ============================
+ 12. Return door → interior.html
+ ============================ -->
+ <a class="hotspot" href="interior.html" aria-label="返回城堡 — Return to castle interior">
+ <title>返回城堡 — Return to castle interior</title>
+ <rect class="hotspot-shape" x="350" y="450" width="100" height="45" rx="4"/>
+ <text class="hotspot-label" x="400" y="478" text-anchor="middle">返回城堡</text>
+ </a>
+ </svg>
+
+ </div>
+
+ <nav id="scene-nav-armory" class="scene-nav" aria-label="兵器库导航">
+ <ul class="scene-nav__list">
+ <li><a class="scene-nav__link" href="#panel-hardware">铁甲 — 硬件</a></li>
+ <li><a class="scene-nav__link" href="#panel-software">法器 — 软件</a></li>
+ <li><a class="scene-nav__link" href="#panel-comms">信物 — 通信</a></li>
+ <li><a class="scene-nav__link" href="#panel-services">契约 — 服务</a></li>
+ <li><a class="scene-nav__link" href="#panel-other">佩饰 — 其他</a></li>
+ <li><a class="scene-nav__link" href="interior.html">返回城堡</a></li>
+ </ul>
+ </nav>
+
+ <!-- ============================================================
+ :target overlay panels — Close-up SVG scenes
+ ============================================================ -->
+
+ <!-- ======================== 1. 铁甲 Hardware ======================== -->
+ <div id="panel-hardware" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-hardware-title" viewBox="0 0 600 500">
+ <title id="closeup-hardware-title">铁甲架特写 — Hardware closeup</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="500"/>
+ <rect class="fill-wall" x="30" y="30" width="540" height="440" rx="4"/>
+
+ <!-- Weapon rack shelf -->
+ <rect class="fill-wall-light" x="30" y="220" width="540" height="6" aria-hidden="true"/>
+ <rect class="fill-wall-dark" x="30" y="30" width="540" height="6" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="26" text-anchor="middle">铁甲</text>
+
+ <!-- Row 1: 4 items -->
+
+ <!-- hw-desktop: 主力台式 (Longsword) -->
+ <g id="hw-desktop" class="closeup-item">
+ <a href="#hw-desktop" aria-label="台式电脑(主力)— Ryzen 5 5600 · GTX 750Ti · 32GB DDR4">
+ <title>台式电脑(主力)— Ryzen 5 5600 · GTX 750Ti · 32GB DDR4</title>
+ <rect class="closeup-item__shape" x="40" y="46" width="120" height="164" rx="4"/>
+ <!-- Longsword -->
+ <rect class="fill-door" x="96" y="56" width="8" height="100"/>
+ <rect class="fill-door" x="82" y="156" width="36" height="8"/>
+ <rect class="fill-door" x="92" y="164" width="16" height="24"/>
+ <text class="closeup-item__name" x="100" y="224" text-anchor="middle">主力台式</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="232" width="260" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="254">台式电脑(主力)</text>
+ <text class="closeup-desc__text" x="52" y="274">Ryzen 5 5600 · GTX 750Ti · 32GB</text>
+ </g>
+ </g>
+
+ <!-- hw-empty: 空虚台式 (Broken sword) -->
+ <g id="hw-empty" class="closeup-item">
+ <a href="#hw-empty" aria-label="台式电脑(空虚)— i3-2100 · P8H61-M LX3 PLUS">
+ <title>台式电脑(空虚)— i3-2100 · P8H61-M LX3 PLUS</title>
+ <rect class="closeup-item__shape" x="175" y="46" width="120" height="164" rx="4"/>
+ <!-- Broken sword: blade snapped at angle -->
+ <rect class="fill-door" x="231" y="56" width="8" height="54"/>
+ <polygon class="fill-door" points="227,110 243,110 239,122 231,118"/>
+ <rect class="fill-door" x="217" y="130" width="36" height="8"/>
+ <rect class="fill-door" x="227" y="138" width="16" height="24"/>
+ <text class="closeup-item__name" x="235" y="224" text-anchor="middle">空虚台式</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="175" y="232" width="260" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="187" y="254">台式电脑(空虚)</text>
+ <text class="closeup-desc__text" x="187" y="274">i3-2100 · P8H61-M LX3 PLUS</text>
+ </g>
+ </g>
+
+ <!-- hw-lost: 迷失台式 (Empty scabbard) -->
+ <g id="hw-lost" class="closeup-item">
+ <a href="#hw-lost" aria-label="台式电脑(迷失)— 配置已失传……">
+ <title>台式电脑(迷失)— 配置已失传……</title>
+ <rect class="closeup-item__shape" x="310" y="46" width="120" height="164" rx="4"/>
+ <!-- Empty scabbard: outline only, hollow center -->
+ <rect class="fill-door" x="358" y="56" width="24" height="106" rx="4"/>
+ <rect class="fill-wall" x="362" y="62" width="16" height="94" rx="2"/>
+ <rect class="fill-door" x="352" y="162" width="36" height="8"/>
+ <text class="closeup-item__name" x="370" y="224" text-anchor="middle">迷失台式</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="310" y="232" width="220" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="322" y="254">台式电脑(迷失)</text>
+ <text class="closeup-desc__text" x="322" y="274">配置已失传……</text>
+ </g>
+ </g>
+
+ <!-- hw-laptop: 笔记本 (Shield) -->
+ <g id="hw-laptop" class="closeup-item">
+ <a href="#hw-laptop" aria-label="笔记本 — Lenovo IdeaPad Flex 5 15">
+ <title>笔记本 — Lenovo IdeaPad Flex 5 15</title>
+ <rect class="closeup-item__shape" x="445" y="46" width="120" height="164" rx="4"/>
+ <!-- Shield -->
+ <polygon class="fill-door" points="505,60 540,60 540,148 522,170 505,148"/>
+ <rect class="fill-wall" x="510" y="100" width="24" height="4"/>
+ <rect class="fill-wall" x="520" y="78" width="4" height="48"/>
+ <text class="closeup-item__name" x="505" y="224" text-anchor="middle">笔记本</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="370" y="232" width="226" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="382" y="254">笔记本</text>
+ <text class="closeup-desc__text" x="382" y="274">Lenovo IdeaPad Flex 5 15</text>
+ </g>
+ </g>
+
+ <!-- Row 2: 3 items centered -->
+
+ <!-- hw-phone: 手机 (Dagger) -->
+ <g id="hw-phone" class="closeup-item">
+ <a href="#hw-phone" aria-label="手机 — Motorola Razr+ 2024">
+ <title>手机 — Motorola Razr+ 2024</title>
+ <rect class="closeup-item__shape" x="80" y="296" width="120" height="140" rx="4"/>
+ <!-- Dagger -->
+ <rect class="fill-door" x="136" y="306" width="8" height="64"/>
+ <polygon class="fill-door" points="136,370 144,370 140,388"/>
+ <rect class="fill-door" x="122" y="298" width="36" height="8"/>
+ <rect class="fill-door" x="132" y="290" width="16" height="12"/>
+ <text class="closeup-item__name" x="140" y="450" text-anchor="middle">手机</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="80" y="450" width="200" height="40" rx="4"/>
+ <text class="closeup-desc__label" x="92" y="468">手机</text>
+ <text class="closeup-desc__text" x="92" y="484">Motorola Razr+ 2024</text>
+ </g>
+ </g>
+
+ <!-- hw-tablet: 平板 (Armor plate) -->
+ <g id="hw-tablet" class="closeup-item">
+ <a href="#hw-tablet" aria-label="平板 — iPad Pro 11 寸">
+ <title>平板 — iPad Pro 11 寸</title>
+ <rect class="closeup-item__shape" x="240" y="296" width="120" height="140" rx="4"/>
+ <!-- Armor plate with rivet lines -->
+ <rect class="fill-door" x="268" y="312" width="64" height="84" rx="4"/>
+ <rect class="fill-wall" x="278" y="326" width="44" height="4"/>
+ <rect class="fill-wall" x="278" y="342" width="44" height="4"/>
+ <rect class="fill-wall" x="278" y="358" width="44" height="4"/>
+ <rect class="fill-wall" x="278" y="374" width="44" height="4"/>
+ <text class="closeup-item__name" x="300" y="450" text-anchor="middle">平板</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="240" y="450" width="170" height="40" rx="4"/>
+ <text class="closeup-desc__label" x="252" y="468">平板</text>
+ <text class="closeup-desc__text" x="252" y="484">iPad Pro 11 寸</text>
+ </g>
+ </g>
+
+ <!-- hw-headphones: 耳机 (Helmet) -->
+ <g id="hw-headphones" class="closeup-item">
+ <a href="#hw-headphones" aria-label="耳机 — Soundcore Liberty 4 NC">
+ <title>耳机 — Soundcore Liberty 4 NC</title>
+ <rect class="closeup-item__shape" x="400" y="296" width="120" height="140" rx="4"/>
+ <!-- Helmet -->
+ <rect class="fill-door" x="426" y="316" width="68" height="60" rx="8"/>
+ <rect class="fill-door" x="420" y="358" width="80" height="18"/>
+ <rect class="fill-wall" x="436" y="312" width="48" height="6"/>
+ <rect class="fill-wall" x="436" y="348" width="48" height="6"/>
+ <text class="closeup-item__name" x="460" y="450" text-anchor="middle">耳机</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="370" y="450" width="220" height="40" rx="4"/>
+ <text class="closeup-desc__label" x="382" y="468">耳机</text>
+ <text class="closeup-desc__text" x="382" y="484">Soundcore Liberty 4 NC</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 2. 法器 Software ======================== -->
+ <div id="panel-software" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-software-title" viewBox="0 0 600 500">
+ <title id="closeup-software-title">法器柜特写 — Software closeup</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="500"/>
+ <rect class="fill-wall" x="30" y="30" width="540" height="440" rx="4"/>
+
+ <!-- Shelf divider -->
+ <rect class="fill-wall-light" x="30" y="220" width="540" height="6" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="26" text-anchor="middle">法器</text>
+
+ <!-- Row 1: 4 items -->
+
+ <!-- sw-os: 操作系统 (Magic book) -->
+ <g id="sw-os" class="closeup-item">
+ <a href="#sw-os" aria-label="操作系统 — EndeavourOS + i3wm / Windows 10">
+ <title>操作系统 — EndeavourOS + i3wm / Windows 10</title>
+ <rect class="closeup-item__shape" x="40" y="46" width="120" height="164" rx="4"/>
+ <!-- Magic book -->
+ <rect class="fill-door" x="68" y="68" width="64" height="86" rx="2"/>
+ <rect class="fill-wall" x="64" y="66" width="6" height="90"/>
+ <rect class="fill-wall" x="78" y="80" width="44" height="3"/>
+ <rect class="fill-wall" x="78" y="92" width="44" height="3"/>
+ <rect class="fill-wall" x="78" y="104" width="44" height="3"/>
+ <rect class="fill-accent-dim" x="88" y="118" width="24" height="24"/>
+ <text class="closeup-item__name" x="100" y="224" text-anchor="middle">操作系统</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="232" width="280" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="254">操作系统</text>
+ <text class="closeup-desc__text" x="52" y="274">EndeavourOS + i3wm / Win 10</text>
+ </g>
+ </g>
+
+ <!-- sw-editor: 编辑器 (Wand) -->
+ <g id="sw-editor" class="closeup-item">
+ <a href="#sw-editor" aria-label="编辑器 — PyCharm · WebStorm · VS Code">
+ <title>编辑器 — PyCharm · WebStorm · VS Code</title>
+ <rect class="closeup-item__shape" x="175" y="46" width="120" height="164" rx="4"/>
+ <!-- Wand -->
+ <rect class="fill-door" x="231" y="68" width="8" height="96"/>
+ <polygon class="fill-accent-dim" points="231,68 239,68 235,54"/>
+ <rect class="fill-wall" x="225" y="134" width="20" height="6"/>
+ <rect class="fill-door" x="229" y="140" width="12" height="18"/>
+ <text class="closeup-item__name" x="235" y="224" text-anchor="middle">编辑器</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="175" y="232" width="280" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="187" y="254">编辑器</text>
+ <text class="closeup-desc__text" x="187" y="274">PyCharm · WebStorm · VS Code</text>
+ </g>
+ </g>
+
+ <!-- sw-terminal: 终端 (Crystal ball) -->
+ <g id="sw-terminal" class="closeup-item">
+ <a href="#sw-terminal" aria-label="终端 — zsh / Windows Terminal">
+ <title>终端 — zsh / Windows Terminal</title>
+ <rect class="closeup-item__shape" x="310" y="46" width="120" height="164" rx="4"/>
+ <!-- Crystal ball on pedestal -->
+ <circle class="fill-door" cx="370" cy="110" r="34"/>
+ <circle class="fill-wall" cx="370" cy="110" r="26"/>
+ <circle class="fill-door" cx="370" cy="110" r="18"/>
+ <rect class="fill-wall-light" x="350" y="144" width="40" height="8"/>
+ <rect class="fill-wall" x="354" y="152" width="32" height="12"/>
+ <text class="closeup-item__name" x="370" y="224" text-anchor="middle">终端</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="310" y="232" width="240" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="322" y="254">终端</text>
+ <text class="closeup-desc__text" x="322" y="274">zsh / Windows Terminal</text>
+ </g>
+ </g>
+
+ <!-- sw-browser: 浏览器 (Telescope) -->
+ <g id="sw-browser" class="closeup-item">
+ <a href="#sw-browser" aria-label="浏览器 — Floorp / Firefox">
+ <title>浏览器 — Floorp / Firefox</title>
+ <rect class="closeup-item__shape" x="445" y="46" width="120" height="164" rx="4"/>
+ <!-- Telescope -->
+ <polygon class="fill-door" points="479,162 484,68 500,64 505,158"/>
+ <circle class="fill-wall" cx="492" cy="64" r="14"/>
+ <circle class="fill-door" cx="492" cy="64" r="10"/>
+ <rect class="fill-wall" x="474" y="158" width="36" height="8"/>
+ <text class="closeup-item__name" x="505" y="224" text-anchor="middle">浏览器</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="400" y="232" width="196" height="56" rx="4"/>
+ <text class="closeup-desc__label" x="412" y="254">浏览器</text>
+ <text class="closeup-desc__text" x="412" y="274">Floorp / Firefox</text>
+ </g>
+ </g>
+
+ <!-- Row 2: 3 items centered -->
+
+ <!-- sw-notes: 笔记 (Quill) -->
+ <g id="sw-notes" class="closeup-item">
+ <a href="#sw-notes" aria-label="笔记 — Emacs · Typora(渐弃)">
+ <title>笔记 — Emacs · Typora(渐弃)</title>
+ <rect class="closeup-item__shape" x="80" y="296" width="120" height="140" rx="4"/>
+ <!-- Quill pen -->
+ <polygon class="fill-door" points="135,300 145,300 142,390 138,390"/>
+ <polygon class="fill-door" points="140,300 118,320 122,326 140,310"/>
+ <polygon class="fill-door" points="140,300 162,320 158,326 140,310"/>
+ <polygon class="fill-accent-dim" points="138,390 142,390 140,408"/>
+ <text class="closeup-item__name" x="140" y="450" text-anchor="middle">笔记</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="80" y="450" width="220" height="40" rx="4"/>
+ <text class="closeup-desc__label" x="92" y="468">笔记</text>
+ <text class="closeup-desc__text" x="92" y="484">Emacs · Typora(渐弃)</text>
+ </g>
+ </g>
+
+ <!-- sw-music: 音乐 (Harp) -->
+ <g id="sw-music" class="closeup-item">
+ <a href="#sw-music" aria-label="音乐 — Navidrome + Tempo / ytmdesktop">
+ <title>音乐 — Navidrome + Tempo / ytmdesktop</title>
+ <rect class="closeup-item__shape" x="240" y="296" width="120" height="140" rx="4"/>
+ <!-- Harp frame -->
+ <polygon class="fill-door" points="276,310 286,310 294,400 284,400"/>
+ <polygon class="fill-door" points="276,310 330,320 330,326 276,316"/>
+ <rect class="fill-door" x="284" y="396" width="46" height="8"/>
+ <!-- Strings -->
+ <rect class="fill-wall" x="294" y="326" width="2" height="70"/>
+ <rect class="fill-wall" x="304" y="328" width="2" height="68"/>
+ <rect class="fill-wall" x="314" y="330" width="2" height="66"/>
+ <text class="closeup-item__name" x="300" y="450" text-anchor="middle">音乐</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="210" y="450" width="280" height="40" rx="4"/>
+ <text class="closeup-desc__label" x="222" y="468">音乐</text>
+ <text class="closeup-desc__text" x="222" y="484">Navidrome + Tempo / ytmdesktop</text>
+ </g>
+ </g>
+
+ <!-- sw-screenshot: 截图 (Catching net) -->
+ <g id="sw-screenshot" class="closeup-item">
+ <a href="#sw-screenshot" aria-label="截图 — FastStone Capture / Flameshot">
+ <title>截图 — FastStone Capture / Flameshot</title>
+ <rect class="closeup-item__shape" x="400" y="296" width="120" height="140" rx="4"/>
+ <!-- Net: handle + ring + mesh -->
+ <rect class="fill-door" x="456" y="370" width="8" height="50"/>
+ <circle class="fill-door" cx="460" cy="344" r="32"/>
+ <circle class="fill-wall" cx="460" cy="344" r="24"/>
+ <!-- Mesh lines -->
+ <rect class="fill-wall" x="446" y="324" width="28" height="2"/>
+ <rect class="fill-wall" x="446" y="336" width="28" height="2"/>
+ <rect class="fill-wall" x="446" y="348" width="28" height="2"/>
+ <rect class="fill-wall" x="446" y="360" width="28" height="2"/>
+ <rect class="fill-wall" x="452" y="322" width="2" height="42"/>
+ <rect class="fill-wall" x="466" y="322" width="2" height="42"/>
+ <text class="closeup-item__name" x="460" y="450" text-anchor="middle">截图</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="360" y="450" width="240" height="40" rx="4"/>
+ <text class="closeup-desc__label" x="372" y="468">截图</text>
+ <text class="closeup-desc__text" x="372" y="484">FastStone Capture / Flameshot</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 3. 信物 Communications ======================== -->
+ <div id="panel-comms" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-comms-title" viewBox="0 0 600 400">
+ <title id="closeup-comms-title">信鸽笼特写 — Communications closeup</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="400"/>
+ <rect class="fill-wall" x="30" y="30" width="540" height="340" rx="4"/>
+
+ <!-- Cage bar divider -->
+ <rect class="fill-wall-light" x="30" y="196" width="540" height="4" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="26" text-anchor="middle">信物</text>
+
+ <!-- Row 1: 2 items -->
+
+ <!-- comm-close: 近交 (Pigeon) -->
+ <g id="comm-close" class="closeup-item">
+ <a href="#comm-close" aria-label="近交 — 微信 · QQ · 贴吧 · 小红书">
+ <title>近交 — 微信 · QQ · 贴吧 · 小红书</title>
+ <rect class="closeup-item__shape" x="40" y="44" width="250" height="142" rx="4"/>
+ <!-- Pigeon body -->
+ <rect class="fill-door" x="130" y="80" width="44" height="32" rx="6"/>
+ <!-- Head -->
+ <rect class="fill-door" x="122" y="70" width="22" height="18" rx="4"/>
+ <!-- Wing -->
+ <polygon class="fill-door" points="174,80 204,68 200,82"/>
+ <!-- Legs -->
+ <rect class="fill-door" x="142" y="112" width="6" height="14"/>
+ <rect class="fill-door" x="158" y="112" width="6" height="14"/>
+ <text class="closeup-item__name" x="165" y="148" text-anchor="middle">近交</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="154" width="250" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="176">近交</text>
+ <text class="closeup-desc__text" x="52" y="194">微信 · QQ · 贴吧 · 小红书</text>
+ </g>
+ </g>
+
+ <!-- comm-far: 远交 (Eagle) -->
+ <g id="comm-far" class="closeup-item">
+ <a href="#comm-far" aria-label="远交 — Instagram · WhatsApp · LinkedIn · GitHub">
+ <title>远交 — Instagram · WhatsApp · LinkedIn · GitHub</title>
+ <rect class="closeup-item__shape" x="310" y="44" width="250" height="142" rx="4"/>
+ <!-- Eagle body -->
+ <rect class="fill-door" x="400" y="82" width="48" height="28" rx="4"/>
+ <!-- Head with beak -->
+ <polygon class="fill-door" points="396,78 412,72 412,84"/>
+ <!-- Wings spread -->
+ <polygon class="fill-door" points="400,82 366,64 380,84"/>
+ <polygon class="fill-door" points="448,82 482,64 468,84"/>
+ <!-- Legs -->
+ <rect class="fill-door" x="416" y="110" width="6" height="16"/>
+ <rect class="fill-door" x="432" y="110" width="6" height="16"/>
+ <text class="closeup-item__name" x="435" y="148" text-anchor="middle">远交</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="310" y="154" width="280" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="322" y="176">远交</text>
+ <text class="closeup-desc__text" x="322" y="194">IG · WhatsApp · LinkedIn · GitHub</text>
+ </g>
+ </g>
+
+ <!-- Row 2: 2 items -->
+
+ <!-- comm-private: 密通 (Sealed letter) -->
+ <g id="comm-private" class="closeup-item">
+ <a href="#comm-private" aria-label="密通 — Signal · Matrix · 短信 · 邮件">
+ <title>密通 — Signal · Matrix · 短信 · 邮件</title>
+ <rect class="closeup-item__shape" x="40" y="208" width="250" height="132" rx="4"/>
+ <!-- Sealed envelope -->
+ <rect class="fill-door" x="120" y="226" width="76" height="52" rx="2"/>
+ <polygon class="fill-wall" points="120,226 158,258 196,226"/>
+ <!-- Wax seal -->
+ <circle class="fill-accent-dim" cx="158" cy="260" r="8"/>
+ <text class="closeup-item__name" x="165" y="304" text-anchor="middle">密通</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="312" width="260" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="334">密通</text>
+ <text class="closeup-desc__text" x="52" y="352">Signal · Matrix · 短信 · 邮件</text>
+ </g>
+ </g>
+
+ <!-- comm-public: 广播 (Horn) -->
+ <g id="comm-public" class="closeup-item">
+ <a href="#comm-public" aria-label="广播 — Mastodon · Pixelfed · 推特 · Facebook">
+ <title>广播 — Mastodon · Pixelfed · 推特 · Facebook</title>
+ <rect class="closeup-item__shape" x="310" y="208" width="250" height="132" rx="4"/>
+ <!-- Horn / trumpet -->
+ <polygon class="fill-door" points="388,268 462,238 462,280 388,276"/>
+ <rect class="fill-door" x="462" y="230" width="14" height="58" rx="4"/>
+ <rect class="fill-wall" x="384" y="266" width="8" height="14"/>
+ <text class="closeup-item__name" x="435" y="304" text-anchor="middle">广播</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="310" y="312" width="280" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="322" y="334">广播</text>
+ <text class="closeup-desc__text" x="322" y="352">Mastodon · Pixelfed · 推特 · FB</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 4. 契约 Services ======================== -->
+ <div id="panel-services" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-services-title" viewBox="0 0 600 500">
+ <title id="closeup-services-title">契书台特写 — Services closeup</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="500"/>
+ <rect class="fill-wall" x="30" y="30" width="540" height="440" rx="4"/>
+
+ <!-- Shelf divider -->
+ <rect class="fill-wall-light" x="30" y="242" width="540" height="6" aria-hidden="true"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="26" text-anchor="middle">契约</text>
+
+ <!-- Row 1: 4 items -->
+
+ <!-- svc-shop: 购物 (Gold pouch) -->
+ <g id="svc-shop" class="closeup-item">
+ <a href="#svc-shop" aria-label="购物 — Amazon Prime">
+ <title>购物 — Amazon Prime</title>
+ <rect class="closeup-item__shape" x="40" y="46" width="120" height="186" rx="4"/>
+ <!-- Gold coin pouch -->
+ <polygon class="fill-door" points="78,100 122,100 132,180 68,180"/>
+ <rect class="fill-wall" x="82" y="92" width="36" height="12"/>
+ <circle class="fill-accent-dim" cx="100" cy="146" r="8"/>
+ <text class="closeup-item__name" x="100" y="246" text-anchor="middle">购物</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="254" width="180" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="276">购物</text>
+ <text class="closeup-desc__text" x="52" y="294">Amazon Prime</text>
+ </g>
+ </g>
+
+ <!-- svc-ai: AI (Magic contract) -->
+ <g id="svc-ai" class="closeup-item">
+ <a href="#svc-ai" aria-label="AI — Claude · Claude Code · Gemini">
+ <title>AI — Claude · Claude Code · Gemini</title>
+ <rect class="closeup-item__shape" x="175" y="46" width="120" height="186" rx="4"/>
+ <!-- Magic contract scroll -->
+ <rect class="fill-door" x="206" y="76" width="58" height="90" rx="2"/>
+ <rect class="fill-wall" x="206" y="76" width="58" height="8" rx="2"/>
+ <rect class="fill-wall" x="206" y="158" width="58" height="8" rx="2"/>
+ <!-- Text lines -->
+ <rect class="fill-wall" x="216" y="94" width="38" height="2"/>
+ <rect class="fill-wall" x="216" y="106" width="38" height="2"/>
+ <rect class="fill-wall" x="216" y="118" width="38" height="2"/>
+ <!-- Magic seal -->
+ <rect class="fill-accent-dim" x="222" y="130" width="26" height="18"/>
+ <text class="closeup-item__name" x="235" y="246" text-anchor="middle">AI</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="175" y="254" width="260" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="187" y="276">AI</text>
+ <text class="closeup-desc__text" x="187" y="294">Claude · Claude Code · Gemini</text>
+ </g>
+ </g>
+
+ <!-- svc-dev: 开发 (Blacksmith contract) -->
+ <g id="svc-dev" class="closeup-item">
+ <a href="#svc-dev" aria-label="开发 — GitHub Pro · GitKraken">
+ <title>开发 — GitHub Pro · GitKraken</title>
+ <rect class="closeup-item__shape" x="310" y="46" width="120" height="186" rx="4"/>
+ <!-- Blacksmith contract (ruled parchment) -->
+ <rect class="fill-door" x="338" y="76" width="64" height="90" rx="2"/>
+ <rect class="fill-wall" x="338" y="76" width="64" height="6"/>
+ <rect class="fill-wall" x="348" y="92" width="44" height="2"/>
+ <rect class="fill-wall" x="348" y="104" width="44" height="2"/>
+ <rect class="fill-wall" x="348" y="116" width="44" height="2"/>
+ <rect class="fill-wall" x="348" y="128" width="44" height="2"/>
+ <rect class="fill-wall" x="348" y="140" width="44" height="2"/>
+ <rect class="fill-wall" x="348" y="152" width="44" height="2"/>
+ <text class="closeup-item__name" x="370" y="246" text-anchor="middle">开发</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="310" y="254" width="240" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="322" y="276">开发</text>
+ <text class="closeup-desc__text" x="322" y="294">GitHub Pro · GitKraken</text>
+ </g>
+ </g>
+
+ <!-- svc-storage: 存储 (Treasure chest) -->
+ <g id="svc-storage" class="closeup-item">
+ <a href="#svc-storage" aria-label="存储 — Google Drive · OneDrive">
+ <title>存储 — Google Drive · OneDrive</title>
+ <rect class="closeup-item__shape" x="445" y="46" width="120" height="186" rx="4"/>
+ <!-- Treasure chest -->
+ <rect class="fill-door" x="470" y="130" width="70" height="44"/>
+ <polygon class="fill-door" points="470,130 540,130 530,104 480,104"/>
+ <rect class="fill-wall" x="470" y="126" width="70" height="6"/>
+ <rect class="fill-wall" x="498" y="138" width="14" height="14" rx="2"/>
+ <text class="closeup-item__name" x="505" y="246" text-anchor="middle">存储</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="400" y="254" width="196" height="50" rx="4"/>
+ <text class="closeup-desc__label" x="412" y="276">存储</text>
+ <text class="closeup-desc__text" x="412" y="294">Google Drive · OneDrive</text>
+ </g>
+ </g>
+
+ <!-- Row 2: 4 items -->
+
+ <!-- svc-infra: 域名·VPS (Land deed) -->
+ <g id="svc-infra" class="closeup-item">
+ <a href="#svc-infra" aria-label="域名·VPS — IONOS · Vultr">
+ <title>域名·VPS — IONOS · Vultr</title>
+ <rect class="closeup-item__shape" x="40" y="308" width="120" height="160" rx="4"/>
+ <!-- Land deed scroll with seal -->
+ <rect class="fill-door" x="66" y="326" width="68" height="96" rx="2"/>
+ <rect class="fill-wall" x="66" y="322" width="68" height="8" rx="2"/>
+ <rect class="fill-wall" x="66" y="418" width="68" height="8" rx="2"/>
+ <rect class="fill-wall" x="78" y="342" width="44" height="2"/>
+ <rect class="fill-wall" x="78" y="356" width="44" height="2"/>
+ <rect class="fill-wall" x="78" y="370" width="44" height="2"/>
+ <circle class="fill-accent-dim" cx="100" cy="398" r="10"/>
+ <text class="closeup-item__name" x="100" y="482" text-anchor="middle">域名·VPS</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="436" width="200" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="52" y="456">IONOS · Vultr</text>
+ </g>
+ </g>
+
+ <!-- svc-movie: 电影 (Theater ticket) -->
+ <g id="svc-movie" class="closeup-item">
+ <a href="#svc-movie" aria-label="电影 — AMC Stubs Premiere">
+ <title>电影 — AMC Stubs Premiere</title>
+ <rect class="closeup-item__shape" x="175" y="308" width="120" height="160" rx="4"/>
+ <!-- Theater ticket -->
+ <rect class="fill-door" x="198" y="340" width="74" height="50" rx="2"/>
+ <rect class="fill-wall" x="198" y="340" width="74" height="6"/>
+ <rect class="fill-wall" x="248" y="346" width="2" height="44"/>
+ <rect class="fill-wall" x="208" y="358" width="34" height="2"/>
+ <rect class="fill-wall" x="208" y="370" width="24" height="2"/>
+ <text class="closeup-item__name" x="235" y="482" text-anchor="middle">电影</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="175" y="436" width="220" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="187" y="456">AMC Stubs Premiere</text>
+ </g>
+ </g>
+
+ <!-- svc-search: 搜索 (Treasure map) -->
+ <g id="svc-search" class="closeup-item">
+ <a href="#svc-search" aria-label="搜索 — Kagi Search">
+ <title>搜索 — Kagi Search</title>
+ <rect class="closeup-item__shape" x="310" y="308" width="120" height="160" rx="4"/>
+ <!-- Treasure map -->
+ <rect class="fill-door" x="334" y="330" width="62" height="76" rx="2"/>
+ <rect class="fill-wall" x="344" y="342" width="22" height="2"/>
+ <rect class="fill-wall" x="344" y="354" width="42" height="2"/>
+ <rect class="fill-wall" x="344" y="366" width="32" height="2"/>
+ <rect class="fill-wall" x="344" y="378" width="42" height="2"/>
+ <!-- X marks the spot -->
+ <circle class="fill-accent-dim" cx="380" cy="392" r="6"/>
+ <text class="closeup-item__name" x="370" y="482" text-anchor="middle">搜索</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="310" y="436" width="180" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="322" y="456">Kagi Search</text>
+ </g>
+ </g>
+
+ <!-- svc-print: 打印 (Seal stamp) -->
+ <g id="svc-print" class="closeup-item">
+ <a href="#svc-print" aria-label="打印 — HP Instant Ink">
+ <title>打印 — HP Instant Ink</title>
+ <rect class="closeup-item__shape" x="445" y="308" width="120" height="160" rx="4"/>
+ <!-- Stamp: handle + block -->
+ <rect class="fill-door" x="488" y="340" width="34" height="10"/>
+ <rect class="fill-door" x="496" y="350" width="18" height="28"/>
+ <rect class="fill-door" x="482" y="378" width="46" height="24" rx="2"/>
+ <text class="closeup-item__name" x="505" y="482" text-anchor="middle">打印</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="445" y="436" width="150" height="30" rx="4"/>
+ <text class="closeup-desc__text" x="457" y="456">HP Instant Ink</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ <!-- ======================== 5. 佩饰 Other ======================== -->
+ <div id="panel-other" class="capsule-panel" tabindex="-1">
+ <svg class="closeup" role="img" aria-labelledby="closeup-other-title" viewBox="0 0 600 300">
+ <title id="closeup-other-title">佩饰匣特写 — Other accessories closeup</title>
+
+ <!-- Background -->
+ <rect class="fill-wall-dark" width="600" height="300"/>
+ <rect class="fill-wall" x="30" y="30" width="540" height="240" rx="4"/>
+
+ <!-- Title -->
+ <text class="closeup-title" x="300" y="26" text-anchor="middle">佩饰</text>
+
+ <!-- 3 items horizontal -->
+
+ <!-- other-pen: 文具 (Fountain pen) -->
+ <g id="other-pen" class="closeup-item">
+ <a href="#other-pen" aria-label="文具 — Pilot 88G 钢笔">
+ <title>文具 — Pilot 88G 钢笔</title>
+ <rect class="closeup-item__shape" x="40" y="46" width="160" height="148" rx="4"/>
+ <!-- Fountain pen -->
+ <rect class="fill-door" x="114" y="62" width="12" height="84"/>
+ <polygon class="fill-door" points="114,146 126,146 120,168"/>
+ <rect class="fill-wall" x="110" y="56" width="20" height="10"/>
+ <rect class="fill-wall" x="112" y="118" width="16" height="4"/>
+ <text class="closeup-item__name" x="120" y="208" text-anchor="middle">文具</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="40" y="216" width="180" height="46" rx="4"/>
+ <text class="closeup-desc__label" x="52" y="236">文具</text>
+ <text class="closeup-desc__text" x="52" y="254">Pilot 88G 钢笔</text>
+ </g>
+ </g>
+
+ <!-- other-watch: 手表 (Watch face) -->
+ <g id="other-watch" class="closeup-item">
+ <a href="#other-watch" aria-label="手表 — CASIO PIKACHU × BABY-G 5338">
+ <title>手表 — CASIO PIKACHU × BABY-G 5338</title>
+ <rect class="closeup-item__shape" x="220" y="46" width="160" height="148" rx="4"/>
+ <!-- Watch: band + face -->
+ <rect class="fill-door" x="282" y="52" width="36" height="22" rx="4"/>
+ <circle class="fill-door" cx="300" cy="118" r="40"/>
+ <circle class="fill-wall" cx="300" cy="118" r="34"/>
+ <circle class="fill-door" cx="300" cy="118" r="28"/>
+ <!-- Hands -->
+ <rect class="fill-wall" x="298" y="94" width="4" height="24"/>
+ <rect class="fill-wall" x="298" y="114" width="20" height="4"/>
+ <!-- Bottom band -->
+ <rect class="fill-door" x="282" y="156" width="36" height="22" rx="4"/>
+ <text class="closeup-item__name" x="300" y="208" text-anchor="middle">手表</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="190" y="216" width="280" height="46" rx="4"/>
+ <text class="closeup-desc__label" x="202" y="236">手表</text>
+ <text class="closeup-desc__text" x="202" y="254">CASIO PIKACHU × BABY-G 5338</text>
+ </g>
+ </g>
+
+ <!-- other-glasses: 眼镜 (Glasses) -->
+ <g id="other-glasses" class="closeup-item">
+ <a href="#other-glasses" aria-label="眼镜 — Vera Wang V906 BK 53-16-137">
+ <title>眼镜 — Vera Wang V906 BK 53-16-137</title>
+ <rect class="closeup-item__shape" x="400" y="46" width="160" height="148" rx="4"/>
+ <!-- Glasses: two lens frames + bridge + temples -->
+ <rect class="fill-door" x="424" y="100" width="48" height="36" rx="10"/>
+ <rect class="fill-door" x="488" y="100" width="48" height="36" rx="10"/>
+ <!-- Bridge -->
+ <rect class="fill-wall" x="472" y="112" width="16" height="6"/>
+ <!-- Temples -->
+ <rect class="fill-door" x="412" y="110" width="14" height="4"/>
+ <rect class="fill-door" x="536" y="110" width="14" height="4"/>
+ <text class="closeup-item__name" x="480" y="208" text-anchor="middle">眼镜</text>
+ </a>
+ <g class="closeup-desc">
+ <rect class="closeup-desc__bg" x="380" y="216" width="210" height="46" rx="4"/>
+ <text class="closeup-desc__label" x="392" y="236">眼镜</text>
+ <text class="closeup-desc__text" x="392" y="254">Vera Wang V906 BK</text>
+ </g>
+ </g>
+ </svg>
+ <a href="#" class="capsule-panel__close">关闭</a>
+ </div>
+
+ </main>
+
+</body>
+</html>